简介:我开始阅读 Javascript 模式一书,但无法理解一个示例。它很大,所以在给你代码之前我会试着简单地解释一下。
例子解释: 所以他们试图做的是在闭包的帮助下定义单例。第一段代码非常简单,但它有一个明显的缺点 - 我们无法在创建 Universe
的第一个实例后重新定义原型(prototype)。
问题: 有人可以解释一下第二个示例(“好”单例)代码如何在第一次构造函数调用后设法更改原型(prototype)吗?
“坏”单例:
function Universe() {
var instance = this;
this.start_time = 0;
this.bang = "Big";
Universe = function () {
return instance;
};
}
// testing
Universe.prototype.nothing = true;
var uni = new Universe();
Universe.prototype.everything = true;
var uni2 = new Universe();
uni.nothing; // true
uni2.nothing; // true
//AS YOU CAN SEE ALL CHANGES TO UNIVERSE PROTOTYPE HAVE NO RESULT AFTER FIRST CONSTRUCTOR CALL
uni.everything; // undefined
uni2.everything; // undefined
然后他们用下面的代码解决了这个问题:
“好”单例:
function Universe() {
var instance;
Universe = function Universe() {
return instance;
};
Universe.prototype = this;
instance = new Universe();
instance.constructor = Universe;
instance.start_time = 0;
instance.bang = "Big";
return instance;
}
// testing
Universe.prototype.nothing = true;
var uni = new Universe();
//QUESTION: how does it manage to change the prototype of singleton?!
Universe.prototype.everything = true;
var uni2 = new Universe();
uni.nothing && uni.everything && uni2.nothing && uni2.everything; // true
换句话说同样的问题:为什么在第一个代码片段中 uni.everything == false
和 uni2.everything == false
但是在第二个 uni.everything == true
和 uni2.everything == true
中呢?至于我,在这两种情况下它们都应该是 false
最佳答案
Note: please feel free to reword this answer to make it sound better, I probably haven't explained it well.
示例 1(“坏”单例)
在你的第一个例子中:
function Universe() {
var instance = this;
this.start_time = 0;
this.bang = "Big";
Universe = function () {
return instance;
};
}
当你第二次调用 new Universe()
时,它返回第一次存储的 instance
(当全局 Universe
构造函数被替换),而不是新对象。这就是为什么对 Universe.prototype
的任何更改都无效。
示例 2(“好”单例)
你的第二个例子有点复杂。第一次调用它时,this
引用最初创建的对象,这意味着它具有带有 nothing
属性的原型(prototype)。由于此对象现在是返回实例的原型(prototype),因此继承了 nothing
属性。
因为现在当您第二次调用 new Universe()
时,它会返回第一次 instance = new Universe()
的结果,对它的任何更改也与它保持一致。
因为您在原始 Universe
函数中返回了 instance
,所以 uni
与 uni2
是同一个对象。
这与这样做的效果相同:
var Universe2;
function Universe() {
Universe2 = function () {
return instance;
};
Universe2.prototype = this;
var instance = new Universe2();
instance.constructor = Universe2;
instance.start_time = 0;
instance.bang = "Big";
return instance;
}
Universe.prototype.nothing = true;
var uni = new Universe();
Universe2.prototype.everything = true;
var uni2 = new Universe2();
然后最终的对象看起来像这样:
==========================
= Object.prototype =
= - hasOwnProperty: ... =
= - toString: ... =
= - ... =
==========================
^
|
|
|
|
==========================
= Universe.prototype: =
= - nothing: true =
==========================
^
|
|
|
|
==========================
= Instance of Universe: =
= - everything: true =
==========================
^
|
|
|
|
==========================
= Instance of Universe2: =
= - start_time: 0 =
= - bang: "Big" =
==========================
关于带有闭包解释的 Javascript Singleton,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25930953/