42

我知道在新的 ES6 模块语法中,JavaScript 引擎不必评估代码即可了解所有导入/导出,它只会解析它并“知道”要加载的内容。

这听起来像吊装。ES6 模块是否被吊起?如果是这样,它们会在运行代码之前全部加载吗?

这段代码可能吗?

import myFunc1 from 'externalModule1';

myFunc2();

if (Math.random()>0.5) {
    import myFunc2 from 'externalModule2';
}
4

3 回答 3

38

在做了更多的研究之后,我发现:

  • 进口被吊起!根据ModuleDeclarationInstantiation规范
  • 在运行任何代码之前,将加载所有依赖模块。

此代码将没有错误,并且可以正常工作:

localFunc();

import {myFunc1} from 'mymodule';

function localFunc() { // localFunc is hoisted
    myFunc1();
}
于 2015-03-29T20:58:30.857 回答
27

这将是一个 SyntaxError。根据规范的这一部分

Module :
   ModuleBody

ModuleBody :
    ModuleItemList

ModuleItemList :
    ModuleItem
    ModuleItemList ModuleItem

ModuleItem :
    ImportDeclaration
    ExportDeclaration
    StatementListItem

这意味着模块只能包含ImportDeclaration's,ExportDeclaration's或StatementListItem's。据此不能 StatementListItem包含ImportDeclaration也不ExportDeclaration

import myFunc1 from 'externalModule1'; 

是一个进口声明,而:

if (Math.random()>0.5) {
    import myFunc2 from 'externalModule2';
}

是一个声明。所以你的代码会导致语法错误。

那么“它们会在运行代码之前全部加载吗?”。这部分规范包含下一句:

注意:在实例化一个模块之前,它请求的所有模块都必须可用。

是的。它们都将在运行代码之前被加载

于 2015-03-29T14:38:09.320 回答
3

ES6 规范可能会发生变化,但这个草案是明确的:

静态变量解析和链接通过检查导入变量名称中的冲突。如果两个导​​入的名称之间存在冲突,或者一个导入的名称与另一个本地绑定之间存在冲突,则这是一个编译时错误。

并且尝试在运行时导入是值得怀疑的想法,不仅在 ES6 中。同样来自草案:

编译解析并验证所有变量定义和引用。链接也发生在编译时;链接解析并验证所有模块导入和导出。

你可以看到Babel 的 ES6 实现对它不太满意。

于 2015-03-29T14:16:03.433 回答