ES6模块进口是否吊装

Are ES6 module imports hoisted?

本文关键字:是否 模块 ES6      更新时间:2023-09-26

我知道在新的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

这意味着模块只能包含ImportDeclarationExportDeclarationStatementListItem。据此StatementListItem可以既不包含ImportDeclaration也不包含ExportDeclaration

import myFunc1 from 'externalModule1'; 

是进口申报,而:

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

是一个声明。因此,您的代码将导致语法错误。

那么"在运行代码之前会全部加载吗?"呢。规范的这一部分包含下一句话:

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

所以,是的它们都将在运行代码之前加载

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

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

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

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

您可以看到Babel的ES6实现对此并不太满意。