我尝试在互联网上搜索导入模块的执行顺序。例如,假设我有以下代码:
import "one"
import "two"
console.log("three");
其中one.js
和two.js
定义如下:
// one.js
console.log("one");
// two.js
console.log("two");
控制台输出是否保证为:
one
two
three
还是未定义的吗?
我尝试在互联网上搜索导入模块的执行顺序。例如,假设我有以下代码:
import "one"
import "two"
console.log("three");
其中one.js
和two.js
定义如下:
// one.js
console.log("one");
// two.js
console.log("two");
控制台输出是否保证为:
one
two
three
还是未定义的吗?
async
属性的<script>
标签不同。当涉及到它们如何加载时,JavaScript模块更接近AMD规范。有关更多详细信息,请参见Axel Rauschmayer的Exploring ES6的第16.6.1节。one
two
three
或者我们可能会看到这个:
two
one
three
console.log()
调用; 它们相互之间是异步的。但它们肯定会在导入它们的模块体之前被执行,因此"three"
保证是最后一个被记录的。await
语句(现在已在Chrome中实现)时,可以观察到模块的异步性。例如,假设我们稍微修改提问者的示例:// main.js
import './one.js';
import './two.js';
console.log('three');
// one.js
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('one');
// two.js
console.log('two');
main.js
时,在控制台中我们会看到以下内容(为了说明添加了时间戳):[0s] two
[1s] one
[1s] three
根据petamoriken的回答,从ES2020开始,非异步模块的评估顺序是有保障的。因此,如果你知道你导入的模块中没有顶层await
语句,它们将按照导入顺序执行。对于提问者的示例,控制台输出将始终为:
one
two
three
module.ExecuteModule()
的顺序是有保证的,因为[[RequestedModules]]是源代码出现的有序列表。// 16.2.1.5.2.1 rough sketch
function InnerModuleEvaluation(module, stack, index) {
// ...
// 8
module.[[PendingAsyncDependencies]] = 0;
// ...
// 11: resolve dependencies (source code occurrences order)
for (required of module.[[RequestedModules]]) {
let requiredModule = HostResolveImportedModule(module, required);
// **recursive**
InnerModuleEvaluation(requiredModule, stack, index);
// ...
if (requiredModule.[[AsyncEvaluation]]) {
++module.[[PendingAsyncDependencies]];
}
}
// 12: execute
if (module.[[PendingAsyncDependencies]] > 0 || module.[[HasTLA]]) {
module.[[AsyncEvaluation]] = true;
if (module.[[PendingAsyncDependencies]] === 0) {
ExecuteAsyncModule(module);
}
} else {
module.ExecuteModule();
}
// ...
}
one
two
three
import
导入。 - Bergi