用JavaScript实现单例模式的最简单/最干净的方法是什么?


当前回答

var singleton = (function () {

    var singleton = function(){
        // Do stuff
    }
    var instance = new singleton();
    return function(){
        return instance;
    }
})();

一个没有getInstance方法的解决方案。

其他回答

我的意见:我有一个构造函数(CF),例如,

var A = function(arg1){
  this.arg1 = arg1
};

我只需要这个CF创建的每个对象都是相同的。

var X = function(){
  var instance = {};
  return function(){ return instance; }
}();

Test

var x1 = new X();
var x2 = new X();
console.log(x1 === x2)
function Unicode()
{
  var i = 0, unicode = {}, zero_padding = "0000", max = 9999;

  // Loop through code points
  while (i < max) {
    // Convert decimal to hex value, find the character,
    // and then pad zeroes to the code point
    unicode[String.fromCharCode(parseInt(i, 16))] = ("u" + zero_padding + i).substr(-4);
    i = i + 1;
  }

  // Replace this function with the resulting lookup table
  Unicode = unicode;
}

// Usage
Unicode();

// Lookup
Unicode["%"]; // Returns 0025

我相信这是最简单/最干净和最直观的方式,尽管它需要ECMAScript 2016 (ES7):

导出默认类Singleton { 静态实例; 构造函数(){ 如果(){ 返回实例; } 这一点。State = "公爵"; 这一点。实例= this; } }

源代码来自:adam-bien.com

我发现下面是最简单的单例模式,因为使用new操作符可以立即在函数中使用它,消除了返回对象字面量的需要:

Var singleton = new(函数(){ var private = "一个私有值"; 这一点。printSomething = function() { console.log(私人); } }) (); singleton.printSomething ();

我不确定我是否同意用模块模式来代替单例模式。我经常看到单例对象在完全没有必要的地方被使用和滥用,我确信模块模式填补了程序员使用单例对象的许多空白。然而,模块模式不是单例的。

模块模式:

var foo = (function () {
    "use strict";
    function aPrivateFunction() {}
    return { aPublicFunction: function () {...}, ... };
}());

在模块模式中初始化的所有内容都在声明Foo时发生。此外,模块模式可用于初始化构造函数,然后可以多次实例化构造函数。虽然模块模式是许多工作的正确工具,但它并不等同于单例模式。

单例模式:

简式

var Foo = function () {
    "use strict";
    if (Foo._instance) {
        // This allows the constructor to be called multiple times
        // and refer to the same instance. Another option is to
        // throw an error.
        return Foo._instance;
    }
    Foo._instance = this;
    // Foo initialization code
};
Foo.getInstance = function () {
    "use strict";
    return Foo._instance || new Foo();
}

长格式,使用模块模式

var Foo = (function () {
    "use strict";
    var instance; //prevent modification of "instance" variable
    function Singleton() {
        if (instance) {
            return instance;
        }
        instance = this;
        //Singleton initialization code
    }
    // Instance accessor
    Singleton.getInstance = function () {
        return instance || new Singleton();
    }
    return Singleton;
}());

在我提供的两个版本的单例模式中,构造函数本身都可以用作访问器:

var a,
    b;
a = new Foo(); // Constructor initialization happens here
b = new Foo();
console.log(a === b); //true

如果你不习惯这样使用构造函数,你可以在If (instance)语句中抛出一个错误,并坚持使用长形式:

var a,
    b;
a = Foo.getInstance(); // Constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); // true

我还应该提到,单例模式很适合隐式构造函数模式:

function Foo() {
    if (Foo._instance) {
        return Foo._instance;
    }
    // If the function wasn't called as a constructor,
    // call it as a constructor and return the result
    if (!(this instanceof Foo)) {
        return new Foo();
    }
    Foo._instance = this;
}
var f = new Foo(); // Calls Foo as a constructor
-or-
var f = Foo(); // Also calls Foo as a constructor