Javascript Singleton与Closure解释

时间:2014-09-19 09:42:40

标签: javascript design-patterns singleton closures

简介:我开始阅读Javascript Patterns一书并且无法掌握一个例子。它非常大,所以我会在给你一个代码之前先简单解释一下。

示例说明:所以他们尝试做的是在Closure的帮助下定义单例。第一段代码非常简单,但它有一个明显的缺点 - 我们无法在创建Universe的第一个实例后重新定义原型。

问题: 有人可以解释一下,第一个构造函数调用之后,第二个示例(“好”单例)代码如何设置更改原型?

'坏'单身:

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 == falseuni2.everything == false中,但在第二个uni.everything == trueuni2.everything == true ?至于我,在两种情况下都应该false

1 个答案:

答案 0 :(得分:4)

  

注意:请随意改写此答案以使其听起来更好,我可能还没有解释清楚。

示例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属性的原型。由于此对象现在是返回实例的原型,因此继承了nothing属性。

因为现在当您第二次致电new Universe()时,它会从第一次返回instance = new Universe()的结果,所以对它的任何更改都会保留。

由于您在原始instance函数中返回了Universe,因此uniuni2的对象相同。

这与此相同:

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"         =
==========================