ES模块系统不保证模块单例吗?
Doesn't ES module system guarantee module singleton?
假设我们有一个依赖模块图,其中多个模块同时导入另一个模块,类似这样:(A) ---> (B) <--- (C)
似乎 ECMAScript 规范不保证 A
和 C
会获得表示 B
模块(或其导出实体)的相同对象实例。
即:一个 JS 模块由一个名为 Abstract Module Record
(its concrete version is Source Text Module Record
) 的规范对象实例表示。这种类型的对象,特别是存储模块的绑定(即,声明的变量名称及其相应的值)。换句话说,不同的 Module Record
有不同的绑定(这是一个非常简单的想法,因为这是我们倾向于使用模块的原因)。
在代码评估之前,Module Record
Link()
method is executed and it, in turn, recursively calls the InitializeEnvironment()
on each of graph Module Record
s. The aim of InitializeEnvironment()
is to create bindings for every imported module. To obtain the needed Module Record
which would represent one of them, this function uses HostResolveImportedModule()
。它接收参数 referencingScriptOrModule
(一个导入模块,即 A
或 C
)和一个字符串 specifier
(类似于 b.js
)。
底线开始出现。
Each time this operation is called with a specific
referencingScriptOrModule
, specifier
pair as arguments it must return
the same Module Record
instance if it completes normally.
我不能从这段摘录中得出保证 A
和 C
会得到相同的实例 Module Record
代表 B
由于 (A, "b.js")
和 (C, "b.js")
不是同一对。
这是否意味着,实际上,ES 模块系统不保证创建模块单例的可能性?有很多关于从模块中导出单例实体的建议。 模块被评估一次然后被缓存,所以这是处理单例的可接受方式。然而,虽然关于缓存的说法是正确的,但这个事实本身并不需要模块系统实现将解析为相同的导入模块 不同 导入模块。
是的,在 ECMAScript 中没有保证 - 如何解析模块说明符的规则由主机决定。
Multiple different referencingScriptOrModule
, specifier
pairs may
map to the same Module Record instance. The actual mapping
semantic is implementation-defined but typically a normalization
process is applied to specifier as part of the mapping process. A
typical normalization process would include actions such as alphabetic
case folding and expansion of relative and abbreviated path
specifiers.
因此只有您的主机(如 node.js 或浏览器)会向您保证它将始终将某些说明符解析为 相同 模块。
有许多示例 (A, "b.js")
和 (C, "b.js")
不应 解析为同一模块 - 例如当 A
是 one/a.js 时,它应该 return 模块 one/b.js,而 C
可能是 two/c.js 并导致模块 two/b.js。
假设我们有一个依赖模块图,其中多个模块同时导入另一个模块,类似这样:(A) ---> (B) <--- (C)
似乎 ECMAScript 规范不保证 A
和 C
会获得表示 B
模块(或其导出实体)的相同对象实例。
即:一个 JS 模块由一个名为 Abstract Module Record
(its concrete version is Source Text Module Record
) 的规范对象实例表示。这种类型的对象,特别是存储模块的绑定(即,声明的变量名称及其相应的值)。换句话说,不同的 Module Record
有不同的绑定(这是一个非常简单的想法,因为这是我们倾向于使用模块的原因)。
在代码评估之前,Module Record
Link()
method is executed and it, in turn, recursively calls the InitializeEnvironment()
on each of graph Module Record
s. The aim of InitializeEnvironment()
is to create bindings for every imported module. To obtain the needed Module Record
which would represent one of them, this function uses HostResolveImportedModule()
。它接收参数 referencingScriptOrModule
(一个导入模块,即 A
或 C
)和一个字符串 specifier
(类似于 b.js
)。
底线开始出现。
Each time this operation is called with a specific
referencingScriptOrModule
,specifier
pair as arguments it must return the sameModule Record
instance if it completes normally.
我不能从这段摘录中得出保证 A
和 C
会得到相同的实例 Module Record
代表 B
由于 (A, "b.js")
和 (C, "b.js")
不是同一对。
这是否意味着,实际上,ES 模块系统不保证创建模块单例的可能性?有很多关于从模块中导出单例实体的建议。
是的,在 ECMAScript 中没有保证 - 如何解析模块说明符的规则由主机决定。
Multiple different
referencingScriptOrModule
,specifier
pairs may map to the same Module Record instance. The actual mapping semantic is implementation-defined but typically a normalization process is applied to specifier as part of the mapping process. A typical normalization process would include actions such as alphabetic case folding and expansion of relative and abbreviated path specifiers.
因此只有您的主机(如 node.js 或浏览器)会向您保证它将始终将某些说明符解析为 相同 模块。
有许多示例 (A, "b.js")
和 (C, "b.js")
不应 解析为同一模块 - 例如当 A
是 one/a.js 时,它应该 return 模块 one/b.js,而 C
可能是 two/c.js 并导致模块 two/b.js。