Simplest/Cleanest way to implement singleton in Ja

2018-12-31 08:48发布

What is the simplest/cleanest way to implement singleton pattern in JavaScript?

30条回答
呛了眼睛熬了心
2楼-- · 2018-12-31 09:29

Isn't this a singleton too?

function Singleton() {
    var i = 0;
    var self = this;

    this.doStuff = function () {
        i = i + 1;
        console.log( 'do stuff',i );
    };

    Singleton = function () { return self };
    return this;
}

s = Singleton();
s.doStuff();
查看更多
弹指情弦暗扣
3楼-- · 2018-12-31 09:29

Singleton in javascript is achieved using Module pattern and closures. Below is the code which is pretty much self-explanatory -

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

cnosole.log(obj1===obj2); //check for type and value. 
查看更多
人间绝色
4楼-- · 2018-12-31 09:31

I think the easiest way is to declare a simple object literal:

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

If you want private members on your singleton instance, you can do something like this:

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

  function privateMethod () {
    // ...
  }

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

This is has been called the module pattern, it basically allows you to encapsulate private members on an object, by taking advantage of the use of closures.

查看更多
余生无你
5楼-- · 2018-12-31 09:31

I needed several singletons with:

  • lazy initialisation
  • initial parameters

and so this was what I came up with:

createSingleton ('a', 'add', [1, 2]);
console.log(a);

function createSingleton (name, construct, args) {
    window[name] = {};
    window[construct].apply(window[name], args);
    window[construct] = null;
}

function add (a, b) {
    this.a = a;
    this.b = b;
    this.sum = a + b;
}
  • args must be Array for this to work so if you have empty variables, just pass in []

  • I used window object in the function but I could have passed in a parameter to create my own scope

  • name and construct parameters are only String for window[] to work but with some simple type-checking, window.name and window.construct are also possible.

查看更多
爱死公子算了
6楼-- · 2018-12-31 09:33

I got this example from JavaScript Patterns Build Better Applications with Coding and Design Patterns By Stoyan Stefanov's book in case you need some simple implementation class like singltone object you can use immediate function as following:

var ClassName;

(function() {
    var instance;
    ClassName = function ClassName() {
        //If private instance variable already initialized return reference
        if(instance) {
            return instance;   
        }
        //If instance does not created save pointer of original reference
        //to private instance variable. 
        instance = this;

        //All constructor initialization will be here
        // i.e.: 
        this.someProperty = 0;
        this.someMethod = function() {
            //Some action here
        };
    };
}());

And you can check this example by following test case:

//Extending defined class like Singltone object using new prototype property
ClassName.prototype.nothing = true;
var obj_1 = new ClassName();
//Extending defined class like Singltone object using new prototype property
ClassName.prototype.everything = true; 
var obj_2 = new ClassName();

//Testing does this two object pointing to same instance
console.log(obj_1 === obj_2); //Result is true, it points to same instance object

//All prototype properites work
//no matter when they were defined
console.log(obj_1.nothing && obj_1.everything 
            && obj_2.nothing && obj_2.everything); //Result true


//Values of properties which is defined inside of constructor
console.log(obj_1.someProperty);// output 0
console.log(obj_2.someProperty);// output 0 
//Changing property value 
obj_1.someProperty = 1;

console.log(obj_1.someProperty);// output 1
console.log(obj_2.someProperty);// output 1

console.log(obj_1.constructor === ClassName); //Output true 

This approaches passes all test cases while private static implementation will fail when prototype extension is used (it can be fixed but it will not be simple) and public static implementation less advisable due to instance is exposed to the public.

jsFiddly demo.

查看更多
高级女魔头
7楼-- · 2018-12-31 09:34

There is more than one ways to skin a cat :) Depending on your taste or specific need you can apply any of the proposed solutions. I personally go for CMS' first solution whenever possible (when you don't need privacy). Since the question was about the simplest and cleanest, that's the winner. Or even:

var myInstance = {}; // done!

This (quote from my blog) ...

var SingletonClass = new function() { 
    this.myFunction() { 
        //do stuff 
    } 
    this.instance = 1; 
}

doesn't make much sense (my blog example doesn't either) because it doesn't need any private vars, so it's pretty much the same as:

var SingletonClass = { 
    myFunction: function () { 
        //do stuff 
    },
    instance: 1 
}
查看更多
登录 后发表回答