我知道在新的 ES6 模块语法中,JavaScript 引擎不必评估代码即可了解所有导入/导出,它只会解析它并“知道”要加载的内容。
这听起来像吊装。ES6 模块是否被吊起?如果是这样,它们会在运行代码之前全部加载吗?
这段代码可能吗?
import myFunc1 from 'externalModule1';
myFunc2();
if (Math.random()>0.5) {
import myFunc2 from 'externalModule2';
}
我知道在新的 ES6 模块语法中,JavaScript 引擎不必评估代码即可了解所有导入/导出,它只会解析它并“知道”要加载的内容。
这听起来像吊装。ES6 模块是否被吊起?如果是这样,它们会在运行代码之前全部加载吗?
这段代码可能吗?
import myFunc1 from 'externalModule1';
myFunc2();
if (Math.random()>0.5) {
import myFunc2 from 'externalModule2';
}
在做了更多的研究之后,我发现:
此代码将没有错误,并且可以正常工作:
localFunc();
import {myFunc1} from 'mymodule';
function localFunc() { // localFunc is hoisted
myFunc1();
}
这将是一个 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';
}
是一个声明。所以你的代码会导致语法错误。
那么“它们会在运行代码之前全部加载吗?”。这部分规范包含下一句:
注意:在实例化一个模块之前,它请求的所有模块都必须可用。
是的。它们都将在运行代码之前被加载。
ES6 规范可能会发生变化,但这个草案是明确的:
静态变量解析和链接通过检查导入变量名称中的冲突。如果两个导入的名称之间存在冲突,或者一个导入的名称与另一个本地绑定之间存在冲突,则这是一个编译时错误。
并且尝试在运行时导入是值得怀疑的想法,不仅在 ES6 中。同样来自草案:
编译解析并验证所有变量定义和引用。链接也发生在编译时;链接解析并验证所有模块导入和导出。
你可以看到Babel 的 ES6 实现对它不太满意。