javascript 是否提升了 ES6 模块导入?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29329662/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 10:23:26  来源:igfitidea点击:

Are ES6 module imports hoisted?

javascriptecmascript-6hoistinges6-modules

提问by gilamran

I know that in the new ES6 module syntax, the JavaScript engine will not have to evaluatethe code to know about all the imports/exports, it will only parseit and “know” what to load.

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

This sounds like hoisting. Are the ES6 modules hoisted? And if so, will they all be loaded before running the code?

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

Is this code possible?

这段代码可以吗?

import myFunc1 from 'externalModule1';

myFunc2();

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

采纳答案by gilamran

After doing some more research, I've found:

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

  • Imports ARE hoisted! according to the specof ModuleDeclarationInstantiation
  • ALL the dependent Modules will be loaded before running any code.
  • 进口大涨!根据规范ModuleDeclarationInstantiation
  • 在运行任何代码之前,将加载所有依赖模块。

This code will have no errors, and will work:

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

localFunc();

import {myFunc1} from 'mymodule';

function localFunc() { // localFunc is hoisted
    myFunc1();
}

回答by alexpods

It will be a SyntaxError. According to this part of specification:

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

Module :
   ModuleBody

ModuleBody :
    ModuleItemList

ModuleItemList :
    ModuleItem
    ModuleItemList ModuleItem

ModuleItem :
    ImportDeclaration
    ExportDeclaration
    StatementListItem

It means that module can contain only ImportDeclaration's, ExportDeclaration's or StatementListItem's. According to thisStatementListItemcould not contain ImportDeclarationnor ExportDeclaration.

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

import myFunc1 from 'externalModule1'; 

is an import declaration, while:

是一个导入声明,而:

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

is a statement. So your code will result to a syntax error.

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

What about "will they all be loaded before running the code?". This part of specificationcontain next sentence:

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

NOTE: Before instantiating a module, all of the modules it requested must be available.

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

So, yeah. They will all be loaded before running the code.

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

回答by Estus Flask

ES6 specification is a subject to change but this draftis explicit:

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

The static variable resolution and linking pass checks for conflicts in imported variable names. If there is a conflict between two imported names, or an imported name and another local binding, then it is a compile-time error.

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

And trying to import at runtime is doubtful idea, not only in ES6. Also from the draft:

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

Compilation resolves and validates all variable definitions and references. Linking also happens at compile-time; linking resolves and validates all module imports and exports.

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

You can see that Babel's ES6 implementationisn't too happy with it.

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