在ES6的`import`语法中,如何精确评估模块?

Han*_*Sun 24 javascript commonjs node.js ecmascript-6 webpack

比方说,我们有四个模块A,B,CD

在模块中A:

console.log("A evaluated")
function AClass {
  console.log("A constructor")
}
var aObj = new AClass()
export default aObj;
Run Code Online (Sandbox Code Playgroud)

在模块中B:

import aObj from A
export default "B"
Run Code Online (Sandbox Code Playgroud)

在模块中C:

import aObj from A
export default "C"
Run Code Online (Sandbox Code Playgroud)

在模块中D:

import b from B
import c from C
import aObj from A
Run Code Online (Sandbox Code Playgroud)

因此,当模块D进行评估,多少次将A evaluatedA constructor被打印到控制台上?

这种行为是否在ES6标准中描述?如果我想要仅对一个模块进行评估,无论直接或间接导入多少次,我该怎么办?有没有人对此有任何想法?

Dmi*_*tin 28

D执行模块,控制台将打印此消息:

A evaluated
A constructor
Run Code Online (Sandbox Code Playgroud)

这意味着A模块仅被评估一次,即使它被其他模块多次导入.

评估规则ES6 modulescommonjs格式相同:

  • 模块是一段加载后执行的代码.这意味着如果主模块中未包含模块,则不会对其进行评估
  • 模块是单身人士.如果多次导入模块,则只instance存在一个模块,并且在加载时仅评估一次

导入相同模块实例的行为描述了ECMAScript 6规范的HostResolveImportedModule部分.
它提到:

如果正常完成,则此操作(导入操作)必须是幂等的.每次使用特定的referencingModule,说明符对(从<source>导入<a>)作为参数调用它时,它必须返回相同的Module Record实例.

模块的单次评估行为在ModuleEvaluation中使用Evaluated布尔标志在第4点和第5点中描述.
每个模块都有一个Evaluated标志,确保只评估一次模块代码.