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


当前回答

下面是一个简单的例子来解释JavaScript中的单例模式。

var Singleton = (function() {
    var instance;
    var init = function() {
        return {
            display:function() {
                alert("This is a singleton pattern demo");
            }
        };
    };
    return {
        getInstance:function(){
            if(!instance){
                alert("Singleton check");
                instance = init();
            }
            return instance;
        }
    };
})();

// In this call first display alert("Singleton check")
// and then alert("This is a singleton pattern demo");
// It means one object is created

var inst = Singleton.getInstance();
inst.display();

// In this call only display alert("This is a singleton pattern demo")
// it means second time new object is not created,
// it uses the already created object

var inst1 = Singleton.getInstance();
inst1.display();

其他回答

你没说"在浏览器里"否则,你可以使用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,因为它没有导出。

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

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

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,那么你可以利用node.JS的缓存机制,你的单例将像这样简单:

class Singleton {
    constructor() {
        this.message = 'I am an instance';
    }
}
module.exports = new Singleton();

请注意,我们导出的不是类Singleton,而是实例Singleton()。

Node.JS将在每次需要时缓存和重用相同的对象。

更多细节请查看:Node.JS和单例模式

我认为最干净的方法是:

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();

2015年ECMAScript (ES6):

class Singleton {
  constructor () {
    if (!Singleton.instance) {
      Singleton.instance = this
    }
    // Initialize object
    return Singleton.instance
  }
  // Properties & Methods
}

const instance = new Singleton()
Object.freeze(instance)

export default instance