Simplest/Cleanest way to implement singleton in JavaScript?

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

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

30条回答
  •  粉色の甜心
    2020-11-22 05:36

    @CMS and @zzzzBov have both given wonderful answers, but just to add my own interpretation based on my having moved into heavy node.js development from PHP/Zend Framework where singleton patterns were common.

    The following, comment-documented code is based on the following requirements:

    • one and only one instance of the function object may be instantiated
    • the instance is not publicly available and may only be accessed through a public method
    • the constructor is not publicly available and may only be instantiated if there is not already an instance available
    • the declaration of the constructor must allow its prototype chain to be modified. This will allow the constructor to inherit from other prototypes, and offer "public" methods for the instance

    My code is very similar to @zzzzBov's except I've added a prototype chain to the constructor and more comments that should help those coming from PHP or a similar language translate traditional OOP to Javascripts prototypical nature. It may not be the "simplest" but I believe it is the most proper.

    // declare 'Singleton' as the returned value of a self-executing anonymous function
    var Singleton = (function () {
        "use strict";
        // 'instance' and 'constructor' should not be availble in a "public" scope
        // here they are "private", thus available only within 
        // the scope of the self-executing anonymous function
        var _instance=null;
        var _constructor = function (name) {
            this.name = name || 'default';
        }
    
        // prototypes will be "public" methods available from the instance
        _constructor.prototype.getName = function () {
            return this.name;
        }
    
        // using the module pattern, return a static object
        // which essentially is a list of "public static" methods
        return {
            // because getInstance is defined within the same scope
            // it can access the "private" 'instance' and 'constructor' vars
            getInstance:function (name) {
                if (!_instance) {
                    console.log('creating'); // this should only happen once
                    _instance = new _constructor(name);
                }
                console.log('returning');
                return _instance;
            }
        }
    
    })(); // self execute
    
    // ensure 'instance' and 'constructor' are unavailable 
    // outside the scope in which they were defined
    // thus making them "private" and not "public"
    console.log(typeof _instance); // undefined
    console.log(typeof _constructor); // undefined
    
    // assign instance to two different variables
    var a = Singleton.getInstance('first');
    var b = Singleton.getInstance('second'); // passing a name here does nothing because the single instance was already instantiated
    
    // ensure 'a' and 'b' are truly equal
    console.log(a === b); // true
    
    console.log(a.getName()); // "first"
    console.log(b.getName()); // also returns "first" because it's the same instance as 'a'
    

    Note that technically, the self-executing anonymous function is itself a Singleton as demonstrated nicely in the code provided by @CMS. The only catch here is that it is not possible to modify the prototype chain of the constructor when the constructor itself is anonymous.

    Keep in mind that to Javascript, the concepts of “public” and “private” do not apply as they do in PHP or Java. But we have achieved the same effect by leveraging Javascript’s rules of functional scope availability.

提交回复
热议问题