javascript - 这个 JS 单例模式如何/为什么工作?

标签 javascript constructor singleton this

我发现了这种创建 JavaScript 单例的相当有趣的方法,它可以使用 new 关键字实例化,例如 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 时,this 都会引用那个新的对象——但是由于构造函数返回了一个完全独立的对象,我认为 this 会被丢弃。但它卡在附近。如何?为什么?

这里有一些我遗漏的微小细节。有人可以照亮它吗?

编辑:原来这段代码是错误的。它“神奇地”似乎持有对实例的引用的原因是因为它实际上静默地将它存储在全局对象中。这充其量是一种糟糕的做法,而且无疑容易出错。

最佳答案

不要被函数getInstance里面的this搞糊涂了,this就是全局对象window , 所以你正在创建一个对象并分配给 window 对象,下次调用构造函数时,你正在检查 window.instance 是否存在。

this.instance = null; 代码毫无意义,只会让你感到困惑。删除它不会改变任何东西。

以下来自MDN .

When the code new foo(...) is executed, the following things happen:

  1. A new object is created, inheriting from foo.prototype.
  2. The constructor function foo is called with the specified arguments and this bound to the newly created object. new foo is equivalent to new foo(), i.e. if no argument list is specified, foo is called without arguments.
  3. The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)

注意step3,当构造函数中有return语句时,返回的结果将是new表达式的结果。

关于javascript - 这个 JS 单例模式如何/为什么工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12683644/

相关文章:

javascript - 在Primefaces中,如何通过javascript中的小部件类型获取小部件

javascript - JS 删除除特定 ID 及其子元素之外的所有元素

javascript - Angular devextreme 风格 dxi-column

javascript - 类型 'length' 上不存在属性 'HTMLElement'

.net - CodeDom 调用构造函数

javascript - 在 JavaScript 中重新分配函数声明

java - 为什么我不应该在类的构造函数中使用 Thread.start()?

c++ - Linux vs Windows std::map 赋值构造函数(为什么会有这样的差异?)

cocoa-touch - 完全解除分配 Objective-C 单例

php数据库单例不返回第二个结果