【问题标题】:Javascript Singleton with Closure explanation带有闭包解释的 Javascript 单例
【发布时间】:2014-09-19 09:42:39
【问题描述】:

简介:我开始阅读 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

换句话说,同样的问题:为什么在第一个代码中 sn-p uni.everything == falseuni2.everything == false 而在第二个代码中是 uni.everything == trueuni2.everything == true?至于我,在这两种情况下都应该是false

【问题讨论】:

  • 当然是,它总是返回第一次创建的实例。
  • @Qantas94Heavy 你刚刚回答了哪个问题?

标签: javascript design-patterns singleton closures


【解决方案1】:

注意:请随意改写这个答案以使其听起来更好,我可能没有很好地解释它。

示例 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() 的结果,因此对它的任何更改也会随之保留。

因为您在原始Universe 函数中返回了instance,所以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"         =
==========================

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    相关资源
    最近更新 更多