使用模块作为单例

lei*_* li 6 javascript node.js

在 javascript 中,我们可以将模块用作单例。

//a.js
export default {str:'aaa'}

//b.js
import singleton from 'a.js'
singleton.str='bbb'

//c.js
import singleton from 'a.js'
singleton.str='ccc'
Run Code Online (Sandbox Code Playgroud)

我想用它来配置我的模块。有什么风险吗?在每个模块系统中它总是一个单例?

Ben*_*aum 11

我想用它来配置我的模块。有风险吗?在每个模块系统中它总是一个单例?

是的,ESM 模块(和 commonjs 模块)保证返回相同的实例。**

虽然这是一个糟糕的设计(因为它是可变的全局状态,任何人都可以导入和更改并且很难跟踪),但它完全保证始终有效。

如果您对 Node.js 如何加载模块的详细信息感兴趣 - 您可以在我们的文档中查看解析器算法的参考,并在此处查看 CommonJS 的相关位


这是值得信赖的。我将尝试解释原因。Imagine 模块不是这样工作的:

//a.js
export default class Foo { /* some code */ }

//b.js
import Foo from './a';
Run Code Online (Sandbox Code Playgroud)

如果每当b其他文件导入该类时,Foo它们可能会得到一个不同的实例 - 诸如此类的东西instanceof无法跨模块工作,并且不可能依赖引用。

通常就是为什么这既得到保证又得到支持的原因。

作为一个有趣的侧面节点 - ES 模块是实时参考:]

**需要注意的是,可以“选择退出” - 例如,通过从 commonjs 中删除模块require.cacherequire.parent在其中进行设置。但是,这绝不是默认行为。