是否提升了 ES6 module导入?

IT技术 javascript ecmascript-6 hoisting es6-modules
2021-03-09 18:58:14

我知道在新的 ES6 module语法中,JavaScript 引擎不必评估代码以了解所有导入/导出,它只会解析它并“知道”要加载什么。

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

这段代码可以吗?

import myFunc1 from 'externalModule1';

myFunc2();

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

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

  • 进口大涨!根据规范ModuleDeclarationInstantiation
  • 在运行任何代码之前,将加载所有依赖module。

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

localFunc();

import {myFunc1} from 'mymodule';

function localFunc() { // localFunc is hoisted
    myFunc1();
}
给定的示例未演示通过导入进行提升。myFunc1 仅用于导入下面的范围。localFunc 本身已被提升,这就是本示例演示的全部内容。
2021-04-30 18:58:14
如果在调用 myFunc1 时调用 localFunc 没有抛出错误,则表明导入已提升。
2021-05-04 18:58:14

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

Module :
   ModuleBody

ModuleBody :
    ModuleItemList

ModuleItemList :
    ModuleItem
    ModuleItemList ModuleItem

ModuleItem :
    ImportDeclaration
    ExportDeclaration
    StatementListItem

这意味着module只能包含ImportDeclaration's、ExportDeclaration's 或StatementListItem's。根据这个 StatementListItem不能包含ImportDeclaration也不能ExportDeclaration

import myFunc1 from 'externalModule1'; 

是一个导入声明,而:

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

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

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

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

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

alexpods,感谢您清理它,但我设法提升了一个导入,而没有将它放在“if”语句中。看到我的回答。
2021-05-08 18:58:14

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

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

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

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

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

不过有人提议,System.require("modulename")左右将允许动态module加载,返回module的Promise。当然,它不会链接到module范围内。
2021-05-12 18:58:14