带有闭包解释的 Javascript Singleton

标签 javascript design-patterns singleton closures

简介:我开始阅读 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 == falseuni2.everything == false但是在第二个 uni.everything == trueuni2.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,所以 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"         =
==========================

关于带有闭包解释的 Javascript Singleton,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25930953/

相关文章:

javascript - 获取数据后返回 JavaScript

javascript - 如何使 Javascript 中的获取 API 模块化

javascript - 不能选择公元前

object - 值对象内部的业务逻辑

c - Objective-C Singleton 实例作为静态?

language-agnostic - 单例 : good design or a crutch?

javascript - 当 preload 设置为 false 时,Node Inspector 仅加载 www 文件

ios - singleton swift 的困难

c# - 一段时间后过期单例实例

java - 在数据库之前处理数据的应用程序设计