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


当前回答

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

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

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

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

其他回答

这就是我如何使用ES6特性实现单例模式。是的,我知道这看起来不像面向对象的方法,但我发现这个方法很容易实现,而且是一种干净的实现方式。

const Singleton = (() => {
  var _instance = !_instance && new Object('Object created....');
  return () => _instance;
})();

//************************************************************************

var instance1 = Singleton();
var instance2 = Singleton();
console.log(instance1 === instance2); // true

我认为最简单的方法是声明一个简单的对象文字:

var myInstance = {
  method1: function () {
    // ...
  },
  method2: function () {
    // ...
  }
};

如果你想在你的单例实例上有私有成员,你可以这样做:

var myInstance = (function() {
  var privateVar = '';

  function privateMethod () {
    // ...
  }

  return { // public interface
    publicMethod1: function () {
      // All private members are accessible here
    },
    publicMethod2: function () {
    }
  };
})();

这被称为模块模式,它基本上允许您通过使用闭包来封装对象上的私有成员。

如果你想阻止对单例对象的修改,你可以使用ES5 object .freeze方法冻结它。

这将使对象不可变,防止对其结构和值进行任何修改。

如果你正在使用ES6,你可以很容易地使用ES模块来表示一个单例,你甚至可以通过在模块范围内声明变量来保持私有状态:

// my-singleton.js
const somePrivateState = []

function privateFn () {
  // ...
}

export default {
  method1() {
    // ...
  },
  method2() {
    // ...
  }
}

然后你可以简单地导入单例对象来使用它:

import myInstance from './my-singleton.js'
// ...

在Node.js版本6中工作:

class Foo {
  constructor(msg) {

    if (Foo.singleton) {
      return Foo.singleton;
    }

    this.msg = msg;
    Foo.singleton = this;
    return Foo.singleton;
  }
}

我们测试:

const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }

简单地使用类表达式:

const singleton = new (class {
    hello() { return 'world'; }
})();

console.log(singleton.hello()); //=> world

您可以在每次新的执行中返回相同的实例-

function Singleton() {
    // lazy 
    if (Singleton.prototype.myInstance == undefined) {
        Singleton.prototype.myInstance = { description: "I am the instance"};
    }
    return Singleton.prototype.myInstance;
}

a = new Singleton();
b = new Singleton();
console.log(a); // { description: "I am the instance"};
console.log(b); // { description: "I am the instance"};
console.log(a==b); // true