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


当前回答

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

这样,您就可以使用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();

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

其他回答

简单的例子

class Settings {

  constructor() {
    if (Settings.instance instanceof Settings) {
      return Settings.instance;
    }
    this.settings = {
      id: Math.floor(Math.random() * 4000),
      name: "background",
    };
    Object.freeze(this.settings);
    Object.freeze(this);
    Settings.instance = this;
  }

}

var o1 = new Settings();
var o2 = new Settings();

console.dir(o1);
console.dir(o2);

if (o1 === o2) {
  console.log("Matched");
}

你没说"在浏览器里"否则,你可以使用Node.js模块。这些对于每个require调用都是相同的。基本的例子:

foo.js的内容: Const circle = require('./circle.js'); console.log('半径为4的圆的面积为${circle.area(4)} '); circle.js的内容: const PI = Math.PI; 出口。area = (r) => PI * r * r; 出口。周长= (r) => 2 * PI * r;

注意,您不能访问圆。PI,因为它没有导出。

虽然这在浏览器中不起作用,但它简单而干净。

对我来说,最干净的方法是:

const singleton = new class {
    name = "foo"
    constructor() {
        console.log(`Singleton ${this.name} constructed`)
    }
}

使用这种语法,您可以确定您的单例是并且将保持惟一的。您还可以享受类语法的甜蜜,并按预期使用它。

(注意,类字段需要节点v12+或现代浏览器。)

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

这样,您就可以使用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();

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

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

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;
        }
    };
};