我尝试从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
相同)。
但如果我在export
声明之后放Kittydar
就可以了:
//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>
标记)。
答案 0 :(得分:5)
标准很难遵循,但文章是正确的。此代码适用于es6draft和SpiderMonkey shell:函数和类都在console.log
调用运行时初始化。
以下是它应该如何工作的细节:
JS引擎解析import.js。它会看到import
声明,因此它会加载export.js并对其进行解析。
在实际运行任何代码之前,系统会创建两个模块范围,并使用每个模块中声明的所有顶级绑定填充它们。 (规范称为ModuleDeclarationInstantiation。)在export.js中创建Kittydar
绑定,但它现在尚未初始化。
在import.js中,创建了Kittydar
导入绑定。它是export.js中Kittydar
绑定的别名。
export.js运行。该类已创建。 Kittydar
已初始化。
import.js运行。两个console.log()
调用都可以正常工作。
Babel对ES6模块的实施是非标准的。
我认为这是故意的。 Babel旨在将ES6模块编译成ES5代码,该代码可与您选择的现有模块系统配合使用:您可以将其吐出AMD模块,UMD,CommonJS等。因此,如果您要求AMD输出,您的代码可能是ES6模块,但ES5输出是一个AMD模块,它的行为就像一个AMD模块。
Babel可能更符合标准,同时仍能很好地与各种模块系统集成,但存在权衡。