在声明之前导出对象和类使它们未定义

mqk*_*lin 4 ecmascript-6 babeljs

我尝试从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
Run Code Online (Sandbox Code Playgroud)

糟糕:Kittydar未定义(顺便说一句,问题与简单相同Object).

但是,如果我exportKittydar声明之后提出它是好的:

//export.js
class Kittydar {}
export {Kittydar};

//import.js
import {Kittydar} from "./export.js";
console.log(Kittydar); // function Kittydar() {_classCallCheck(this, Kittydar);}
Run Code Online (Sandbox Code Playgroud)

这篇文章中的拼写错误吗?

我把它与之结合起来babel并捆绑在一起browserify.然后我将输出包包含在通常的.html文件中(带<script>标签).

Jas*_*rff 5

该标准很难遵循,但文章是正确的.此代码适用于es6draft和SpiderMonkey shell:函数和类都在这些console.log调用运行时初始化.

以下是它应该如何工作的细节:

  • JS引擎解析import.js.它看到import声明,然后它加载export.js并解析它.

  • 在实际运行任何代码之前,系统会创建两个模块范围,并使用在每个模块中声明的所有顶级绑定填充它们.(规范调用此ModuleDeclarationInstantiation.)Kittydar在export.js中创建绑定,但它现在尚未初始化.

    在import.js中,创建了一个Kittydar 导入绑定.它是Kittydarexport.js中绑定的别名.

  • export.js运行.该类已创建.Kittydar已初始化.

  • import.js运行.这两个console.log()电话都很好.


Babel对ES6模块的实现是非标准的.

我认为这是故意的.Babel旨在将ES6模块编译成ES5代码,该代码可与您选择的现有模块系统配合使用:您可以将其吐出AMD模块,UMD,CommonJS等.因此,如果您要求AMD输出,您的代码可能是ES6模块,但ES5输出是一个AMD模块,它的行为就像一个AMD模块.

Babel可能更符合标准,同时仍能很好地与各种模块系统集成,但存在权衡.