我在以下代码中窥探了以下内容:
var Log = require('log');
// This creates a singleton instance
module.exports = new Log('info');
我的第一反应是"不是单身"但我记得有一篇文章概述了Node.js如何require()
语句说了一些关于缓存需要的语句并在后续使用它们调用
基本上我的问题是,导出new Object()
实际上是在幕后创建单身?
我知道还有其他方法可以在JavaScript中创建单例,但这似乎是在Node内部实现它的一种非常方便的方法(如果它确实有效)。
答案 0 :(得分:2)
是的,这是Node.js中最接近Singleton的东西。 require()
在第一次调用时缓存每个模块,因此每个后续require()
都返回相同的实例。
但是,您必须意识到这并不总是强制执行。可以修改/删除缓存,也可以使用其完整路径缓存模块,简而言之,这意味着如果您在包中定义单例并且您的包作为嵌套依赖项安装,则可能在您的“单例”中有多个实例同一应用程序的上下文。 快速举例:
Application
node_modules
PackageA
node_modules
YourPackageWithSingleton
PackageB
node_modules
YourPackageWithSingleton
通常您不必担心这一点,但如果您确实需要在整个应用程序中共享一个对象,唯一的解决方案是使用全局(不鼓励)或依赖注入。
答案 1 :(得分:1)
由于您可以根据需要创建尽可能多的Log
实例,因此它不是真正的单例。但你可以像这样使用它。否则,您只需通过var mySingleton = {}
创建一个普通对象,并将属性和方法附加到它。
然后,您可以将mySingleton
分配给module.exports
,将require()
分配给其他模块。
foo.js:
var mySingleton = {
someMethod = function () {}
};
module.exports = mySingleton;
bar.js:
var singletonClass = require('./foo.js');
singletonClass.someMethod();
答案 2 :(得分:1)
为什么不亲自测试一下?
$ cat test.js
module.exports = Math.random();
$ node
> var a = require("./test");
undefined
> var a = require("./test");
undefined
> a === b
true
是的,似乎node.js确实缓存了导出的值。因此,如果您再次需要相同的模块,它将返回缓存的值,而不是创建新值。
但应注意,程序员可以require("log")
手动创建新实例。所以从这个意义上来说,它不是一个单身人士。