用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 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'
// ...

这个知识是基于我正在学习Java,虽然Java和Javascript是不同的,但单例的概念和Java如何做到这一点是一样的。在我看来,JS的类样式本身是干净的,而不是var初始化。

class Singleton {
    // use hashtag which entails that the variable can only be accessed from self scope
    static #instance = null;
    static getInstance() {
        if (this.#instance === null) this.#instance = new Singleton();
        return this.#instance;
    }

    // some class property
    hello = 'world';

    // or initialize the variable in the constructor, depend on your preference
    constructor() {
        // this.hello = 'world';
    }

    /* you can also add parameters on the constructor & getInstance
     * e.g. 
     * static getInstance(param1, param2) {...new Singleton(param1, param2)}
     * constructor(param1, param2) {...}
     */

}




// this is the same code for java and normal way for singleton for class
// just use static so you can get instance


// testing the singleton
var s1,s2;
s1 = Singleton.getInstance();
s2 = Singleton.getInstance();

// you cannot access the property, immediately
if (Singleton.hello === undefined) console.log('getInstance so you can access this');

console.log(s1.hello);
// result: "world"

console.log(s2.hello);
// result: "world"


// set the value of Singleton object
s2.hello = "hi";
    console.log(s1.hello);
    // result: "hi"

    console.log(s2.hello);
    // result: "hi"
// this is just an evidence which means that they are the same even in property level

if (s1 === s2) console.log("S1 & S2 is the same object");
// result: "S1 & S2 is the same object"

// don't use something like `var s1 = new Singleton();`
// this will defeat your purpose of just (1 object), one instance of class

JavaScript中的单例是使用模块模式和闭包实现的。

下面的代码是不言自明的

// Singleton example.
var singleton = (function() {
  var instance;

  function init() {
    var privateVar1 = "this is a private variable";
    var privateVar2 = "another var";

    function pubMethod() {
      // Accessing private variables from inside.
      console.log(this.privateVar1);
      console.log(this.privateVar2);
      console.log("inside of a public method");
    };
  }

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

  return {
    getInstance: getInstance
  }
})();

var obj1 = singleton.getInstance();
var obj2 = singleton.getInstance();

console.log(obj1 === obj2); // Check for type and value.

我认为最干净的方法是:

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 = new (function() {
  var bar = 123

  this.foo = function() {
    // Whatever
  }
})()