让我们从一个问题开始。ES2015模块increment
包含以下代码:
let counter = 0;
counter++;
export default counter;
在另一个模块(我们将称为)中consumer
,上述模块被导入了2次:
import counter1 from './increment';
import counter2 from './increment';
counter1;
counter2;
现在,实际上是一个问题。变量counter1
和counter2
模块之后有consumer
什么?
为了回答这个问题,您需要了解JavaScript如何执行模块以及如何导入模块。
模块执行
为了了解内部JavaScript机制是如何工作的,请仔细阅读规范。根据规范,每个JavaScript模块都与Module Record实体相关联。此项具有Evaluate()
模块执行的方法:如果此模块已经成功执行,则返回undefined;否则,返回false。[...]。否则,可传递地执行此模块的所有依赖项,然后执行此模块。结果,证明同一模块仅执行一次。不幸的是,您需要知道的回答我们的问题的不仅限于此。如何确保指令调用import
使用相同的路径会返回相同的模块吗?允许导入命令
抽象操作HostResolveImportedModule()负责将模块(指定者)的路径与特定模块相关联。模块导入代码如下所示:import module from 'path';
规格说明如下:HostResolveImportedModule的实现必须满足以下要求:- 正常的返回值应该是Module Record的特定子类的实例。
- 如果对应于对referenceingScriptOrModule对的Module Record实体不存在,说明符不存在,或者无法创建这样的实体,则将引发异常。
- 每次调用该操作并将其作为参数传递给特定的一对referenceingScriptOrModule指定符时,在其通常执行的情况下,它应返回Module Record实体的相同实例。
现在以更易理解的方式考虑这一点。HostResolveImportedModule(referencingScriptOrModule, specifier)
-一个抽象的操作,返回对应于一对的参数模块referencingScriptOrModule
,specifier
:- 参数
referencingScriptOrModule
是当前模块,即导入的模块。 - 参数
specifier
是与指令中的模块路径匹配的字符串import
。
在描述的最后,HostResolveImportedModule()
可以说当导入对应于相同路径的模块时,将导入相同的模块:import moduleA from 'path';
import moduleB from 'path';
import moduleC from 'path';
moduleA === moduleB;
moduleB === moduleC;
有趣的是,该规范表明主机(浏览器,Node.js环境,通常是任何尝试执行JavaScript代码的主机)都应提供特定的实现HostResolveImportedModule()
。回答
在仔细阅读了规范之后,很明显JavaScript模块在导入期间仅执行一次。当使用相同的路径导入模块时,将返回模块的相同实例。让我们回到我们的问题。一个模块increment
总是只执行一次:
let counter = 0;
counter++;
export default counter;
无论模块导入了多少次increment
,一个表达式counter++
仅被评估一次。counter
使用默认导出机制导出的变量很重要1
。现在看一下模块consumer
:
import counter1 from './increment';
import counter2 from './increment';
counter1;
counter2;
命令import counter1 from './increment'
和import counter2 from './increment'
使用相同的路径- './increment'
。结果,结果是导入了模块的相同实例。事实证明,相同的值1 被写入到变量counter1
和counter2
到consumer
。摘要
通过研究一个简单的问题,我们能够找到有关如何执行和导入JavaScript模块的更多信息。导入模块时使用的规则非常简单:同一模块仅执行一次。换句话说,模块级别范围内的操作仅执行一次。如果再次导入已经执行过的模块,则不会再次执行。导入模块时,它使用从上一会话获得的结果来找出其确切导出的内容。如果多次导入一个模块,但是模块说明符(指向它的路径)保持不变,那么JavaScript规范将确保导入相同的模块实例。亲爱的读者们! 您多久阅读一次JavaScript规范,弄清某些语言结构的功能特性?