我发现了这种创建 JavaScript 单例的相当有趣的方法,它可以使用 new
关键字实例化,例如 var x = new SingletonClass()
。我对变量范围和闭包等有很好的了解,但我很难理解为什么这段代码会这样工作。
// EDIT: DO NOT USE this code; see the answers below
function SingletonClass() {
this.instance = null;
var things = [];
function getInstance() {
if (!this.instance) {
this.instance = {
add: function(thing) {
things.push(thing);
},
list: function() {
console.log(things.toString());
}
};
}
return this.instance;
}
return getInstance();
}
var obj1 = new SingletonClass();
obj1.add("apple");
obj1.list(); //"apple"
var obj2 = new SingletonClass();
obj2.add("banana");
obj1.list(); //"apple,banana"
obj2.list(); //"apple,banana"
obj1.add("carrot");
obj1.list(); //"apple,banana,carrot"
obj2.list(); //"apple,banana,carrot"
我的直觉告诉我,每次实例化一个新的 SingletonClass
时,this
都会引用那个新的对象——但是由于构造函数返回了一个完全独立的对象,我认为 this
会被丢弃。但它卡在附近。如何?为什么?
这里有一些我遗漏的微小细节。有人可以照亮它吗?
编辑:原来这段代码是错误的。它“神奇地”似乎持有对实例的引用的原因是因为它实际上静默地将它存储在全局对象中。这充其量是一种糟糕的做法,而且无疑容易出错。
最佳答案
不要被函数getInstance
里面的this
搞糊涂了,this
就是全局对象window
, 所以你正在创建一个对象并分配给 window 对象,下次调用构造函数时,你正在检查 window.instance
是否存在。
this.instance = null;
代码毫无意义,只会让你感到困惑。删除它不会改变任何东西。
以下来自MDN .
When the code
new foo(...)
is executed, the following things happen:
- A new object is created, inheriting from foo.prototype.
- The constructor function foo is called with the specified arguments and this bound to the newly created object. new foo is equivalent to
new foo()
, i.e. if no argument list is specified, foo is called without arguments.- The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
注意step3,当构造函数中有return语句时,返回的结果将是new表达式的结果。
关于javascript - 这个 JS 单例模式如何/为什么工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12683644/