Simplest/Cleanest way to implement singleton in JavaScript?

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

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

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

    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.

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

    You can do it with decorators like in this example below for TypeScript:

    class YourClass {
    
        @Singleton static singleton() {}
    
    }
    
    function Singleton(target, name, descriptor) {
        var instance;
        descriptor.value = () => {
            if(!instance) instance = new target;
            return instance;
        };
    }
    

    Then you use your singleton like this:

    var myInstance = YourClass.singleton();
    

    As of this writing, decorators are not readily available in JavaScript engines. You would need to make sure your JavaScript runtime has decorators actually enabled or use compilers like Babel and TypeScript.

    Also note that singleton instance is created "lazy", i.e., it is created only when you use it for the first time.

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

    The clearest answer should be this one from the book Learning JavaScript Design Patterns by Addy Osmani.

    var mySingleton = (function () {
     
      // Instance stores a reference to the Singleton
      var instance;
     
      function init() {
     
        // Singleton
     
        // Private methods and variables
        function privateMethod(){
            console.log( "I am private" );
        }
     
        var privateVariable = "Im also private";
     
        var privateRandomNumber = Math.random();
     
        return {
     
          // Public methods and variables
          publicMethod: function () {
            console.log( "The public can see me!" );
          },
     
          publicProperty: "I am also public",
     
          getRandomNumber: function() {
            return privateRandomNumber;
          }
     
        };
     
      };
     
      return {
     
        // Get the Singleton instance if one exists
        // or create one if it doesn't
        getInstance: function () {
     
          if ( !instance ) {
            instance = init();
          }
     
          return instance;
        }
     
      };
     
    })();

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

    How about this way, just insure the class can not new again.

    By this, you can use the instanceof op, also, you can use the prototype chain to inherit the class,it's a regular class, but can not new it,if yuu want to get the instance just use getInstance

    function CA()
    {
        if(CA.instance)
        {
            throw new Error('can not new this class');
        }else{
            CA.instance = this;
        }
    
    }
    /**
     * @protected
     * @static
     * @type {CA}
     */
    CA.instance = null;
    /** @static */
    CA.getInstance = function()
    {
        return CA.instance;
    }
    
    CA.prototype = 
    /** @lends CA#*/
    {
        func: function(){console.log('the func');}
    }
    // initilize the instance
    new CA();
    
    // test here
    var c = CA.getInstance()
    c.func();
    console.assert(c instanceof CA)
    // this will failed
    var b = new CA();
    

    If you don't want to expose the instance member, just put it into a closure.

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

    I believe this is the simplest/cleanest and most intuitive way though it requires ES7:

    export default class Singleton {
    
      static instance;
    
      constructor(){
        if(instance){
          return instance;
        }
    
        this.state = "duke";
        this.instance = this;
      }
    
    }
    

    The source code is from: adam-bien.com

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

    What's wrong with this?

    function Klass() {
       var instance = this;
       Klass = function () { return instance; }
    }
    
    0 讨论(0)
提交回复
热议问题