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


当前回答

模块模式:“更具可读性的风格”。您可以很容易地看到哪些方法是公共的,哪些是私有的

var module = (function(_name){
   /* Local Methods & Values */
   var _local = {
      name : _name,
      flags : {
        init : false
      }
   }

   function init(){
     _local.flags.init = true;
   }

   function imaprivatemethod(){
     alert("Hi, I'm a private method");
   }

   /* Public Methods & variables */

   var $r = {}; // This object will hold all public methods.

   $r.methdo1 = function(){
       console.log("method1 calls it");
   }

   $r.method2 = function(){
      imaprivatemethod(); // Calling private method
   }

   $r.init = function(){
      inti(); // Making 'init' public in case you want to init manually and not automatically
   }

   init(); // Automatically calling the init method

   return $r; // Returning all public methods

})("module");

现在你可以使用公共方法,比如

module.method2 ();// ->我正在调用一个私有方法超过一个公共方法警报(“嗨,我是一个私有方法”)

http://jsfiddle.net/ncubica/xMwS9/

其他回答

我反对我的回答,看看我的另一个。

通常,模块模式(参见Christian C. Salvadó的答案)不是单例模式就足够好了。然而,单例的一个特点是它的初始化会延迟到需要对象时。模块模式缺乏这个特性。

我的命题(CoffeeScript):

window.singleton = (initializer) ->
  instance = undefined
  () ->
    return instance unless instance is undefined
    instance = initializer()

在JavaScript中编译为:

window.singleton = function(initializer) {
    var instance;
    instance = void 0;
    return function() {
        if (instance !== void 0) {
            return instance;
        }
        return instance = initializer();
    };
};

然后我可以做以下事情:

window.iAmSingleton = singleton(function() {
    /* This function should create and initialize singleton. */
    alert("creating");
    return {property1: 'value1', property2: 'value2'};
});


alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up

简单地使用类表达式:

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

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

模块模式:“更具可读性的风格”。您可以很容易地看到哪些方法是公共的,哪些是私有的

var module = (function(_name){
   /* Local Methods & Values */
   var _local = {
      name : _name,
      flags : {
        init : false
      }
   }

   function init(){
     _local.flags.init = true;
   }

   function imaprivatemethod(){
     alert("Hi, I'm a private method");
   }

   /* Public Methods & variables */

   var $r = {}; // This object will hold all public methods.

   $r.methdo1 = function(){
       console.log("method1 calls it");
   }

   $r.method2 = function(){
      imaprivatemethod(); // Calling private method
   }

   $r.init = function(){
      inti(); // Making 'init' public in case you want to init manually and not automatically
   }

   init(); // Automatically calling the init method

   return $r; // Returning all public methods

})("module");

现在你可以使用公共方法,比如

module.method2 ();// ->我正在调用一个私有方法超过一个公共方法警报(“嗨,我是一个私有方法”)

http://jsfiddle.net/ncubica/xMwS9/

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

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

这应该可以工作:

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