ES6导入的定义执行顺序是什么?

Max*_*Max 28 javascript ecmascript-6 es6-module-loader

我试过在互联网上搜索导入模块的执行顺序.例如,假设我有以下代码:

import "one"
import "two"
console.log("three");
Run Code Online (Sandbox Code Playgroud)

其中one.jstwo.js定义如下:

// one.js
console.log("one");

// two.js
console.log("two");
Run Code Online (Sandbox Code Playgroud)

控制台输出是否保证为:

one
two
three
Run Code Online (Sandbox Code Playgroud)

还是未定义?

McM*_*ath 27

导入的ES6模块以异步方式执行.但是,所有导入都在执行导入的脚本之前执行.这使得ES6模块与Node.js模块或没有该属性的<script>标签不同async.在加载时,ES6模块更接近AMD规范.有关更多详细信息,请参阅Axel Rauschmayer 的探索ES6第16.6.1节.

因此,在上面提供的示例中,无法保证执行顺序.有两种可能的结果.你可能会看到这个:

one
two
three
Run Code Online (Sandbox Code Playgroud)

或者您可能会看到:

two
one
three
Run Code Online (Sandbox Code Playgroud)

换句话说,两个导入的模块可以console.log()按任何顺序执行其调用; 它们是异步相对于彼此.但它们肯定会在导入它们的脚本之前执行,因此"three"保证最后记录.

也就是说,没有现代浏览器实现ES6模块.我不知道像Babel这样的转发器是否遵循这方面的原始规范.

更新

根据@ BenjaminGruenbaum的评论,我决定更密切地研究这个问题.尽管上面有上述内容,但我无法在规范本身中明确指出模块加载是异步的(尽管可以肯定的是,作为英语母语人士,我发现规范有点难以阅读).如果是这种情况,那么执行导入的顺序将取决于实现.也就是说,同样的结论认为:您不能指望您的进口按任何特定顺序执行.

  • 关于“导入的 ES6 模块是异步执行的。”的任何参考? (3认同)
  • 据我所知,ES2015 模块 _not_ 异步导入,而是 - 它们如何加载完全取决于模块加载器。 (2认同)
  • @BenjaminGruenbaum是的,这就是为什么要添加一个警告:“没有现代浏览器实现ES6模块。我不知道Babel这样的编译器在这方面是否遵循原始规范。” 我怀疑大多数此类转译程序确实会按照您的建议同步导入。但是我的答案是关于原始规范的。 (2认同)
  • 我实际上是那本书的评论家。我要说的一点是,决定它的不是 ES 模块规范 - 由模块 _loaded_ 规范决定如何加载模块。IIRC 规范仅要求在代码执行时加载所有模块。 (2认同)

pet*_*ken 9

根据最新规范InnerModuleEvaluation ,由于[[RequestedModules]] 是源代码出现的有序列表,因此module.ExecuteModule()保证了 的顺序。

// 16.2.1.5.2.1 rough sketch
function InnerModuleEvaluation(module, stack, index) {

  // ...

  // 8
  module.[[PendingAsyncDependencies]] = 0;

  // ...

  // 11: resolve dependencies (source code occurrences order)
  for (required of module.[[RequestedModules]]) {
    let requiredModule = HostResolveImportedModule(module, required);
    // **recursive**
    InnerModuleEvaluation(requiredModule, stack, index);

    // ...

    if (requiredModule.[[AsyncEvaluation]]) {
      ++module.[[PendingAsyncDependencies]];
    }
  }

  // 12: execute
  if (module.[[PendingAsyncDependencies]] > 0 || module.[[HasTLA]]) {
    module.[[AsyncEvaluation]] = true;
    if (module.[[PendingAsyncDependencies]] === 0) {
      ExecuteAsyncModule(module);
    }
  } else {
    module.ExecuteModule();
  }

  // ...

}
Run Code Online (Sandbox Code Playgroud)

控制台输出始终如下:

one
two
three
Run Code Online (Sandbox Code Playgroud)