在声明未定义之前导出 objects 和 类
Export objects and classes before their declaration makes them undefined
我尝试重复 Mozilla Hacks 中的示例(导出列表 副标题):
//export.js
export {detectCats, Kittydar};
function detectCats() {}
class Kittydar {}
//import.js
import {detectCats, Kittydar} from "./export.js";
console.log(detectCats); // function detectCats() {}
console.log(Kittydar); // undefined
糟糕:Kittydar 未定义(顺便说一句,问题与简单 Object
相同)。
但是如果我在 Kittydar
声明之后放置 export
就可以了:
//export.js
class Kittydar {}
export {Kittydar};
//import.js
import {Kittydar} from "./export.js";
console.log(Kittydar); // function Kittydar() {_classCallCheck(this, Kittydar);}
这是文章中的错字吗?
我用 babel
编译它并用 browserify
捆绑。然后我将输出包包含在一个通常的 .html
文件中(带有 <script>
标签)。
这个标准很难遵循,但是这篇文章是正确的。此代码在 es6draft 和 SpiderMonkey shell 中有效:函数和 class 都在 console.log
调用 运行.[=19 时初始化=]
这是它应该如何工作的详细信息:
JS引擎解析import.js。它看到 import
声明,因此它加载 export.js 并解析它。
在实际 运行 任何代码之前,系统会创建两个模块范围并使用每个模块中声明的所有 top-level 绑定填充它们。 (规范称之为 ModuleDeclarationInstantiation。)在 export.js 中创建了 Kittydar
绑定,但目前尚未初始化。
在 import.js 中,创建了一个 Kittydar
导入绑定 。它是 export.js 中 Kittydar
绑定的别名。
export.js运行秒。 class 已创建。 Kittydar
已初始化。
import.js运行秒。 console.log()
两个调用都工作正常。
Babel 对 ES6 模块的实现是非标准的。
我认为这是故意的。 Babel 旨在将 ES6 模块编译成 ES5 代码,该代码可与您选择的现有模块系统一起使用:您可以让它吐出 AMD 模块、UMD、CommonJS 等。因此,如果您要求 AMD 输出,您的代码可能是 ES6 模块,但是 ES5 输出是一个 AMD 模块,它的行为将像一个 AMD 模块。
Babel 可能会更好 standard-compliant,同时仍然与各种模块系统很好地集成,但需要权衡取舍。
我尝试重复 Mozilla Hacks 中的示例(导出列表 副标题):
//export.js
export {detectCats, Kittydar};
function detectCats() {}
class Kittydar {}
//import.js
import {detectCats, Kittydar} from "./export.js";
console.log(detectCats); // function detectCats() {}
console.log(Kittydar); // undefined
糟糕:Kittydar 未定义(顺便说一句,问题与简单 Object
相同)。
但是如果我在 Kittydar
声明之后放置 export
就可以了:
//export.js
class Kittydar {}
export {Kittydar};
//import.js
import {Kittydar} from "./export.js";
console.log(Kittydar); // function Kittydar() {_classCallCheck(this, Kittydar);}
这是文章中的错字吗?
我用 babel
编译它并用 browserify
捆绑。然后我将输出包包含在一个通常的 .html
文件中(带有 <script>
标签)。
这个标准很难遵循,但是这篇文章是正确的。此代码在 es6draft 和 SpiderMonkey shell 中有效:函数和 class 都在 console.log
调用 运行.[=19 时初始化=]
这是它应该如何工作的详细信息:
JS引擎解析import.js。它看到
import
声明,因此它加载 export.js 并解析它。在实际 运行 任何代码之前,系统会创建两个模块范围并使用每个模块中声明的所有 top-level 绑定填充它们。 (规范称之为 ModuleDeclarationInstantiation。)在 export.js 中创建了
Kittydar
绑定,但目前尚未初始化。在 import.js 中,创建了一个
Kittydar
导入绑定 。它是 export.js 中Kittydar
绑定的别名。export.js运行秒。 class 已创建。
Kittydar
已初始化。import.js运行秒。
console.log()
两个调用都工作正常。
Babel 对 ES6 模块的实现是非标准的。
我认为这是故意的。 Babel 旨在将 ES6 模块编译成 ES5 代码,该代码可与您选择的现有模块系统一起使用:您可以让它吐出 AMD 模块、UMD、CommonJS 等。因此,如果您要求 AMD 输出,您的代码可能是 ES6 模块,但是 ES5 输出是一个 AMD 模块,它的行为将像一个 AMD 模块。
Babel 可能会更好 standard-compliant,同时仍然与各种模块系统很好地集成,但需要权衡取舍。