我遇到了一种相当有趣的方法来创建一个可以用new
关键字实例化的 JavaScript 单例,例如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
实例化一个 new 时,都this
指的是那个新的新对象——但是由于构造函数返回了一个完全独立的对象,我认为this
它只会被丢弃。但它徘徊。如何?为什么?
这里有一些我遗漏的小细节。任何人都可以照亮它吗?
编辑:原来这段代码很糟糕。它“神奇地”似乎持有对实例的引用的原因是因为它实际上默默地将它存储在全局对象中。这充其量是不好的做法,而且无疑容易出错。