Simplest/Cleanest way to implement singleton in JavaScript?

后端 未结 30 997
名媛妹妹
名媛妹妹 2020-11-22 05:17

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

相关标签:
30条回答
  • 2020-11-22 05:26

    following is the snippet from my walk through to implement a singleton pattern. This occurred to me during an interview process and I felt that I should capture this somewhere.

    /*************************************************
       *     SINGLETON PATTERN IMPLEMENTATION          *
       *************************************************/
    
      //since there are no classes in javascript, every object is technically a singleton
      //if you don't inherit from it or copy from it.
      var single = {};
      //Singleton Implementations
      //Declaring as a Global Object...you are being judged!
    
    
      var Logger = function() {
        //global_log is/will be defined in GLOBAL scope here
        if(typeof global_log === 'undefined'){
          global_log = this;
        }
        return global_log;
      };
    
    
      //the below 'fix' solves the GLOABL variable problem but
      //the log_instance is publicly available and thus can be 
    
      //tampered with.
      function Logger() {
        if(typeof Logger.log_instance === 'undefined'){
          Logger.log_instance = this;
        }
    
    
        return Logger.log_instance;
       };
    
    
      //the correct way to do it to give it a closure!
    
    
      function logFactory() {
        var log_instance; //private instance
        var _initLog = function() { //private init method
          log_instance = 'initialized';
          console.log("logger initialized!")
        }
        return {
          getLog : function(){ //the 'privileged' method 
            if(typeof log_instance === 'undefined'){
              _initLog();
            }
            return log_instance;
          }
        };
      }
    
      /***** TEST CODE ************************************************
      //using the Logger singleton
      var logger = logFactory();//did i just gave LogFactory a closure?
      //create an instance of the logger
      var a = logger.getLog();
      //do some work
      //get another instance of the logger
      var b = logger.getLog();
    
    
      //check if the two logger instances are same?
      console.log(a === b); //true
      *******************************************************************/
    

    the same can be found on my gist page

    0 讨论(0)
  • 2020-11-22 05:28

    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.

    0 讨论(0)
  • 2020-11-22 05:31

    The following works in node v6

    class Foo {
      constructor(msg) {
    
        if (Foo.singleton) {
          return Foo.singleton;
        }
    
        this.msg = msg;
        Foo.singleton = this;
        return Foo.singleton;
      }
    }
    

    We test:

    const f = new Foo('blah');
    const d = new Foo('nope');
    console.log(f); // => Foo { msg: 'blah' }
    console.log(d); // => Foo { msg: 'blah' }
    
    0 讨论(0)
  • 2020-11-22 05:32

    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 accessible here
        },
        publicMethod2: function () {
        }
      };
    })();
    

    This 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.

    UPDATE: I would like to add that if you want to prevent the modification of the singleton object, you can freeze it, using the ES5 Object.freeze method.

    That will make the object immutable, preventing any modification to the its structure and values.

    Additionally I would like to mention that if you are using ES6, you can represent a singleton using ES Modules very easily, and you can even hold private state by declaring variables at the module scope:

    // my-singleton.js
    const somePrivateState = []
    
    function privateFn () {
      // ...
    }
    
    export default {
      method1() {
        // ...
      },
      method2() {
        // ...
      }
    }
    

    Then you can simply import the singleton object to use it:

    import myInstance from './my-singleton.js'
    // ...
    
    0 讨论(0)
  • 2020-11-22 05:32

    Simplest/Cleanest for me means also simply to understand and no bells & whistles as are much discussed in the Java version of the discussion:

    What is an efficient way to implement a singleton pattern in Java?

    The answer that would fit simplest/cleanest best there from my point of view is:

    https://stackoverflow.com/a/70824/1497139

    And it can only partly be translated to JavaScript. Some of the difference in Javascript are:

    • constructors can't be private
    • Classes can't have declared fields

    But given latest ECMA syntax it is possible to get close with:

    Singleton pattern as JavaScript class example

     class Singleton {
    
      constructor(field1,field2) {
        this.field1=field1;
        this.field2=field2;
        Singleton.instance=this;
      }
    
      static getInstance() {
        if (!Singleton.instance) {
          Singleton.instance=new Singleton('DefaultField1','DefaultField2');
        }
        return Singleton.instance;
      }
    }
    

    Example Usage

    console.log(Singleton.getInstance().field1);
    console.log(Singleton.getInstance().field2);
    

    Example Result

    DefaultField1
    DefaultField2
    
    0 讨论(0)
  • 2020-11-22 05:34

    Singleton:

    Ensure a class has only one instance and provide a global point of access to it.

    The Singleton Pattern limits the number of instances of a particular object to just one. This single instance is called the singleton.

    • defines getInstance() which returns the unique instance.
    • responsible for creating and managing the instance object.

    The Singleton object is implemented as an immediate anonymous function. The function executes immediately by wrapping it in brackets followed by two additional brackets. It is called anonymous because it doesn't have a name.

    Sample Program,

    var Singleton = (function () {
        var instance;
     
        function createInstance() {
            var object = new Object("I am the instance");
            return object;
        }
     
        return {
            getInstance: function () {
                if (!instance) {
                    instance = createInstance();
                }
                return instance;
            }
        };
    })();
     
    function run() {
     
        var instance1 = Singleton.getInstance();
        var instance2 = Singleton.getInstance();
     
        alert("Same instance? " + (instance1 === instance2));  
    }
    
    run()

    0 讨论(0)
提交回复
热议问题