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


当前回答

我认为最干净的方法是:

var SingletonFactory = (function(){
    function SingletonClass() {
        //do stuff
    }
    var instance;
    return {
        getInstance: function(){
            if (instance == null) {
                instance = new SingletonClass();
                // Hide the constructor so the returned object can't be new'd...
                instance.constructor = null;
            }
            return instance;
        }
   };
})();

之后,可以调用函数as

var test = SingletonFactory.getInstance();

其他回答

关键是要理解闭包背后的重要性。因此,在闭包的帮助下,即使在内部函数内部的属性也将是私有的。

var Singleton = function () {
    var instance;

    function init() {

       function privateMethod() {
           console.log("private via closure");
       }

       var privateVariable = "Private Property";

       var privateRandomNumber = Math.random(); // This is also private

       return {
           getRandomNumber: function () {  // Access via getter in init call
               return privateRandomNumber;
           }
       };
    };

    return {
        getInstance: function () {

            if (!instance) {
                instance = init();
            }
            return instance;
        }
    };
};

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

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

源代码来自:adam-bien.com

这应该可以工作:

function Klass() {
   var instance = this;
   Klass = function () { return instance; }
}

另一种方法-只是确保类不能再新的。

这样,您就可以使用instanceof op。此外,您还可以使用原型链来继承类。这是一个普通的课程,但是你不能去学。如果你想获取实例,只需使用getInstance:

function CA()
{
    if(CA.instance)
    {
        throw new Error('can not new this class');
    }
    else
    {
        CA.instance = this;
    }
}


/**
 * @protected
 * @static
 * @type {CA}
 */
CA.instance = null;

/* @static */
CA.getInstance = function()
{
    return CA.instance;
}


CA.prototype =
/** @lends CA# */
{
    func: function(){console.log('the func');}
}

// Initialise the instance
new CA();

// Test here
var c = CA.getInstance()
c.func();
console.assert(c instanceof CA)

// This will fail
var b = new CA();

如果不想公开实例成员,只需将其放入闭包中。

你可以用下面这个例子中的TypeScript装饰器来做:

class YourClass {

    @Singleton static singleton() {}

}

function Singleton(target, name, descriptor) {
    var instance;
    descriptor.value = () => {
        if(!instance) instance = new target;
        return instance;
    };
}

然后你像这样使用你的单例:

var myInstance = YourClass.singleton();

在撰写本文时,JavaScript引擎中还没有装饰器。你需要确保你的JavaScript运行时实际上启用了装饰器,或者使用像Babel和TypeScript这样的编译器。

还要注意的是,单例实例是“惰性”创建的,也就是说,只有当你第一次使用它时才会创建它。