¿La forma más sencilla/limpia de implementar singleton en JavaScript?


¿Cuál es la forma más sencilla/limpia de implementar el patrón singleton en JavaScript?

Author: RzR, 2009-09-26

30 answers

Creo que la forma más fácil es declarar un objeto simple literal:

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

Si desea miembros privados en su instancia de singleton, puede hacer algo como esto:

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

  function privateMethod () {
    // ...
  }

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

Esto se ha llamado el patrón de módulo , básicamente le permite encapsular miembros privados en un objeto, aprovechando el uso de closures.

 283
Author: CMS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-25 20:15:48

Creo que el enfoque más limpio es algo como:

var SingletonClass = (function(){
    function SingletonClass() {
        //do stuff
    }
    var instance;
    return {
        getInstance: function(){
            if (instance == null) {
                instance = new SingletonClass();
                // Hide the constructor so the returned objected can't be new'd...
                instance.constructor = null;
            }
            return instance;
        }
   };
})();

Después, puede invocar la función como

var test = SingletonClass.getInstance();
 151
Author: sebarmeli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-18 23:39:07

No estoy seguro de estar de acuerdo con el patrón de módulo que se utiliza como un reemplazo para un patrón singleton. A menudo he visto singleton usados y abusados en lugares donde son totalmente innecesarios, y estoy seguro de que el patrón del módulo llena muchos vacíos donde los programadores de otra manera usarían un singleton, sin embargo el patrón del módulo es no un singleton.

Patrón del módulo:

var foo = (function () {
    "use strict";
    function aPrivateFunction() {}
    return { aPublicFunction: function () {...}, ... };
}());

Todo lo inicializado en el patrón del módulo sucede cuando se declara Foo. Además, el módulo pattern se puede usar para inicializar un constructor, que luego podría ser instanciado varias veces. Si bien el patrón de módulo es la herramienta adecuada para muchos trabajos, no es equivalente a un singleton.

Patrón único:

forma abreviada
var Foo = function () {
    "use strict";
    if (Foo._instance) {
        //this allows the constructor to be called multiple times
        //and refer to the same instance. Another option is to
        //throw an error.
        return Foo._instance;
    }
    Foo._instance = this;
    //Foo initialization code
};
Foo.getInstance = function () {
    "use strict";
    return Foo._instance || new Foo();
}
forma larga, usando el patrón del módulo
var Foo = (function () {
    "use strict";
    var instance; //prevent modification of "instance" variable
    function Singleton() {
        if (instance) {
            return instance;
        }
        instance = this;
        //Singleton initialization code
    }
    //instance accessor
    Singleton.getInstance = function () {
        return instance || new Singleton();
    }
    return Singleton;
}());

En ambas versiones del patrón Singleton que he proporcionado, el constructor en sí puede ser utilizado como el accessor:

var a,
    b;
a = new Foo(); //constructor initialization happens here
b = new Foo();
console.log(a === b); //true

Si no se siente cómodo usando el constructor de esta manera, puede lanzar un error en la instrucción if (instance), y seguir usando la forma larga:

var a,
    b;
a = Foo.getInstance(); //constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); //true

También debo mencionar que el patrón singleton encaja bien con el patrón de la función constructora implícita:

function Foo() {
    if (Foo._instance) {
        return Foo._instance;
    }
    //if the function wasn't called as a constructor,
    //call it as a constructor and return the result
    if (!(this instanceof Foo)) {
        return new Foo();
    }
    Foo._instance = this;
}
var f = new Foo(); //calls Foo as a constructor
-or-
var f = Foo(); //also calls Foo as a constructor
 91
Author: zzzzBov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-09 00:20:28

Hay más de una manera de pelar un gato :) Dependiendo de su gusto o necesidad específica puede aplicar cualquiera de las soluciones propuestas. Personalmente opto por la primera solución de CMS siempre que sea posible (cuando no necesita privacidad). Dado que la pregunta era sobre la más simple y limpia, ese es el ganador. O incluso:

var myInstance = {}; // done!

Esto (cita de mi blog)...

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

No tiene mucho sentido (mi ejemplo de blog tampoco) porque no necesita ningún var privado, por lo que es más o menos lo mismo que:

var SingletonClass = { 
    myFunction: function () { 
        //do stuff 
    },
    instance: 1 
}
 8
Author: Stoyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-28 01:04:55

Desapruebo mi respuesta, véasemi otra .

Por lo general, el patrón de módulo (consulte la respuesta de CMS) que NO es un patrón de singleton es lo suficientemente bueno. Sin embargo, una de las características de singleton es que su inicialización se retrasa hasta que se necesita el objeto. Module pattern carece de esta característica.

Mi proposición (CoffeeScript):

window.singleton = (initializer) ->
  instance = undefined
  () ->
    return instance unless instance is undefined
    instance = initializer()

Que compiló esto en JavaScript:

window.singleton = function(initializer) {
    var instance;
    instance = void 0;
    return function() {
        if (instance !== void 0) {
            return instance;
        }
        return instance = initializer();
    };
};

Entonces puedo hacer lo siguiente:

window.iAmSingleton = singleton(function() {
    /* This function should create and initialize singleton. */
    alert("creating");
    return {property1: 'value1', property2: 'value2'};
});


alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up
 7
Author: skalee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:03:05

Obtuve este ejemplo de Patrones JavaScript Cree Mejores Aplicaciones con Patrones de Codificación y Diseño Por Stoyan Stefanov en caso de que necesite alguna clase de implementación simple como el objeto singltone, puede usar la función inmediata de la siguiente manera:

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

Y puedes comprobar este ejemplo siguiendo el caso de prueba:

//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 

Este enfoque pasa todos los casos de prueba, mientras que la implementación estática privada fallará cuando se use la extensión del prototipo (se puede arreglar, pero no sea simple) y la implementación estática pública es menos aconsejable debido a que la instancia está expuesta al público.

JsFiddly demo.

 6
Author: Khamidulla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-21 06:54:35

Respuesta corta:

Debido a la naturaleza no bloqueante de JavaScript, los Singletons en JavaScript son realmente feos en su uso. Las variables globales le darán una instancia a través de toda la aplicación también sin todas estas devoluciones de llamada, module pattern oculta suavemente los elementos internos detrás de la interfaz. Ver respuesta @ CMS.

Pero, ya que querías un singleton {{[9]]}

var singleton = function(initializer) {

  var state = 'initial';
  var instance;
  var queue = [];

  var instanceReady = function(createdInstance) {
    state = 'ready';
    instance = createdInstance;
    while (callback = queue.shift()) {
      callback(instance);
    }
  };

  return function(callback) {
    if (state === 'initial') {
      state = 'waiting';
      queue.push(callback);
      initializer(instanceReady);
    } else if (state === 'waiting') {
      queue.push(callback);
    } else {
      callback(instance);
    }
  };

};

Uso:

var singletonInitializer = function(instanceReady) {
  var preparedObject = {property: 'value'};
  // calling instanceReady notifies singleton that instance is ready to use
  instanceReady(preparedObject);
}
var s = singleton(singletonInitializer);

// get instance and use it
s(function(instance) {
  instance.doSomething();
});

Explicación:

Los singletons le dan más de una instancia a través de toda la aplicación: su inicialización se retrasa hasta el primer uso. Esto es realmente importante cuando se trata de objetos cuya inicialización es costosa. Caro generalmente significa E/S y en JavaScript I / O siempre significa devoluciones de llamada.

No confíes en las respuestas que te dan una interfaz como instance = singleton.getInstance(), todas pierden el punto.

Si no aceptan la devolución de llamada para ejecutarse cuando la instancia está lista, entonces no funcionarán cuando el inicializador haga E/S.

Sí, las devoluciones de llamada siempre se ven más feas que la función llamada que devuelve inmediatamente la instancia del objeto. Pero de nuevo: cuando haces E/S, las devoluciones de llamada son obligatorias. Si no desea hacer ninguna E/S, entonces la instanciación es lo suficientemente barata como para hacerlo al inicio del programa.

Ejemplo 1, inicializador barato:

var simpleInitializer = function(instanceReady) {
  console.log("Initializer started");
  instanceReady({property: "initial value"});
}

var simple = singleton(simpleInitializer);

console.log("Tests started. Singleton instance should not be initalized yet.");

simple(function(inst) {
  console.log("Access 1");
  console.log("Current property value: " + inst.property);
  console.log("Let's reassign this property");
  inst.property = "new value";
});
simple(function(inst) {
  console.log("Access 2");
  console.log("Current property value: " + inst.property);
});

Ejemplo 2, inicialización con E/S:

En este ejemplo setTimeout falsifica alguna operación de E/S costosa. Esto ilustra por qué los singletons en JavaScript realmente necesitan callbacks.

var heavyInitializer = function(instanceReady) {
  console.log("Initializer started");
  var onTimeout = function() {
    console.log("Initializer did his heavy work");
    instanceReady({property: "initial value"});
  };
  setTimeout(onTimeout, 500);
};

var heavy = singleton(heavyInitializer);

console.log("In this example we will be trying");
console.log("to access singleton twice before it finishes initialization.");

heavy(function(inst) {
  console.log("Access 1");
  console.log("Current property value: " + inst.property);
  console.log("Let's reassign this property");
  inst.property = "new value";
});

heavy(function(inst) {
  console.log("Access 2. You can see callbacks order is preserved.");
  console.log("Current property value: " + inst.property);
});

console.log("We made it to the end of the file. Instance is not ready yet.");
 5
Author: skalee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-19 09:01:41

Creo que he encontrado la forma más limpia de programar en JavaScript, pero necesitarás un poco de imaginación. Obtuve esta idea de una técnica de trabajo en el libro "javascript the good parts".

En lugar de usar la palabra clave new, puedes crear una clase como esta:

function Class()
{
    var obj = {}; // Could also be used for inheritence if you don't start with an empty object.

    var privateVar;
    obj.publicVar;

    obj.publicMethod= publicMethod;
    function publicMethod(){} 

    function privateMethod(){} 

    return obj;
}

Puede crear una instancia del objeto anterior diciendo:

var objInst = Class(); // !!! NO NEW KEYWORD

Ahora con este método de trabajo en mente, podría crear un singleton como este:

ClassSingleton = function()
{
    var instance= null;

    function Class() // This is the class like the above one
    {
        var obj = {};
        return obj;
    }

    function getInstance()
    {
        if( !instance )
            instance = Class(); // Again no new keyword;

        return instance;
    }   

    return { getInstance : getInstance };

}();

Ahora puede obtener su instancia por llamando

var obj = ClassSingleton.getInstance();

Creo que esta es la manera más ordenada ya que la "Clase" completa ni siquiera es accesible.

 5
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-02 12:18:36

@CMS y @zzzzBov han dado respuestas maravillosas, pero solo para agregar mi propia interpretación basada en que me he movido a heavy node.desarrollo de js desde PHP / Zend Framework donde los patrones singleton eran comunes.

El siguiente código documentado por comentarios se basa en los siguientes requisitos:

  • una y solo una instancia del objeto de función puede ser instanciada
  • la instancia no está disponible públicamente y solo se puede acceder a través de un método
  • el constructor no está disponible públicamente y solo puede ser instanciado si no hay ya una instancia disponible
  • la declaración del constructor debe permitir que se modifique su cadena de prototipos. Esto permitirá al constructor heredar de otros prototipos, y ofrecer métodos "públicos" para la instancia

Mi código es muy similar al de @zzzzBov, excepto que he agregado una cadena de prototipos al constructor y más comentarios que deberían ayudar a los que vienen de PHP o un lenguaje similar traducen OOP tradicional a Javascripts de naturaleza prototípica. Puede que no sea el "más simple", pero creo que es el más apropiado.

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

Tenga en cuenta que técnicamente, la función anónima autoejecutable es en sí misma un Singleton como se demuestra muy bien en el código proporcionado por @CMS. El único problema aquí es que no es posible modificar la cadena de prototipos del constructor cuando el propio constructor es anónimo.

Tenga en cuenta que para Javascript, la los conceptos de "público" y "privado" no se aplican como lo hacen en PHP o Java. Pero hemos logrado el mismo efecto aprovechando las reglas de Javascript de disponibilidad de alcance funcional.

 4
Author: talentedmrjones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-16 21:38:46

No estoy seguro de por qué nadie mencionó esto, pero simplemente podría hacer:

var singleton = new (function() {
  var bar = 123

  this.foo = function() {
    // whatever
  }
})()
 4
Author: Derek Chiang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-22 03:15:30

En es6:

class Singleton {
  constructor () {
    if (!Singleton.instance) {
      Singleton.instance = this
    }
    // Initialize object
    return Singleton.instance
  }
  // Properties & Methods
}

const instance = new Singleton()
Object.freeze(instance)

export default instance
 4
Author: Xaqron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-12 19:53:47

La respuesta más clara debería ser esta del libro Learning JavaScript Design Patterns de 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;
    }
 
  };
 
})();
 4
Author: 令狐葱,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-10 07:28:22

Puedo poner mis 5 monedas. Tengo una función constructora, por ejemplo.

var A = function(arg1){
  this.arg1 = arg1  
};

Lo que necesito hacer es que cada objeto creado por este CF será el mismo.

var X = function(){
  var instance = {};
  return function(){ return instance; }
}();

Prueba

var x1 = new X();
var x2 = new X();
console.log(x1 === x2)
 2
Author: Andrii Olenchenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-03 07:39:02

Lo siguiente funciona en el nodo v6

class Foo {
  constructor(msg) {

    if (Foo.singleton) {
      return Foo.singleton;
    }

    this.msg = msg;
    Foo.singleton = this;
    return Foo.singleton;
  }
}

Probamos:

const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }
 2
Author: Daniel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-26 08:53:54

He encontrado que el siguiente es el patrón Singleton más fácil, porque usando el operador new hace que este esté inmediatamente disponible dentro de la función, eliminando la necesidad de devolver un objeto literal:

var singleton = new (function () {

  var private = "A private value";
  
  this.printSomething = function() {
      console.log(private);
  }
})();

singleton.printSomething();
 2
Author: Mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 05:40:47

Necesitaba varios singletons con:

  • inicialización perezosa
  • parámetros iniciales

Así que esto fue lo que se me ocurrió:

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 debe ser matriz para que esto funcione, por lo que si tiene variables vacías, solo pasar []

  • Utilicé el objeto window en la función, pero podría haber pasado un parámetro para crear mi propio ámbito

  • Los parámetros de nombre y construcción son solo cadenas para que window [] funcione, pero con algunos comprobación de tipo simple, window.name y ventana.construir también son posibles.

 1
Author: fred,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-29 12:17:55

¿Qué tiene de malo esto?

function Klass() {
   var instance = this;
   Klass = function () { return instance; }
}
 1
Author: Manav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-04 02:40:48

¿Qué tal de esta manera, solo asegúrese de que la clase no puede nuevo de nuevo.

Por esto, puede usar el instanceof op, también, puede usar la cadena de prototipos para heredar la clase, es una clase regular, pero no puede nueva,si yuu quiere obtener la instancia solo 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();

Si no desea exponer el miembro instance, simplemente póngalo en un cierre.

 1
Author: wener,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-29 12:01:48

A continuación se muestra el fragmento de mi recorrido para implementar un patrón singleton. Esto se me ocurrió durante un proceso de entrevista y sentí que debía capturar esto en algún lugar.

/*************************************************
   *     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
  *******************************************************************/

Lo mismo se puede encontrar en mi gist página

 1
Author: curioussam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-23 17:27:23
function Unicode()
  {
  var i = 0, unicode = {}, zero_padding = "0000", max = 9999;
  //Loop through code points
  while (i < max) {
    //Convert decimal to hex value, find the character, then pad zeroes to the codepoint
    unicode[String.fromCharCode(parseInt(i, 16))] = ("u" + zero_padding + i).substr(-4);
    i = i + 1;
    }

  //Replace this function with the resulting lookup table
  Unicode = unicode;
  }

//Usage
Unicode();
//Lookup
Unicode["%"]; //returns 0025
 1
Author: Paul Sweatte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-23 22:43:52

¿No es esto un singleton también?

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();
 1
Author: Nawal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-24 13:29:39

Puede hacerlo con decoradores como en este ejemplo a continuación para TypeScript:

class YourClass {

    @Singleton static singleton() {}

}

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

Luego usa tu singleton de esta manera:

var myInstance = YourClass.singleton();

Al momento de escribir este artículo, los decoradores no están fácilmente disponibles en los motores JavaScript. Tendría que asegurarse de que su tiempo de ejecución de JavaScript tiene decoradores realmente habilitados o usar compiladores como Babel y TypeScript.

También tenga en cuenta que la instancia de singleton se crea "perezosa", es decir, se crea solo cuando se usa por primera vez.

 1
Author: Vad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-26 11:22:24

Patrón de módulo: en "estilo más legible". Puede ver fácilmente qué métodos son públicos y cuáles son privados

var module = (function(_name){
   /*Local Methods & Values*/
   var _local = {
      name : _name,
      flags : {
        init : false
      }
   }

   function init(){
     _local.flags.init = true;
   }

   function imaprivatemethod(){
     alert("hi im a private method");
   }

   /*Public Methods & variables*/

   var $r = {}; //this object will hold all public methods.

   $r.methdo1 = function(){
       console.log("method1 call it");
   }

   $r.method2 = function(){
      imaprivatemethod(); //calling private method
   }

   $r.init = function(){
      inti(); //making init public in case you want to init manually and not automatically
   }

   init(); //automatically calling init method

   return $r; //returning all publics methods

})("module");

Ahora puedes usar métodos públicos como

Módulo.method2 (); / / - > Estoy llamando a un método privado sobre una alerta de método público("hi im a private method")

Http://jsfiddle.net/ncubica/xMwS9 /

 1
Author: ncubica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-07 16:33:24

Singleton:

Asegúrese de que una clase tenga solo una instancia y proporcione un punto de acceso global a ella.

El Patrón Singleton limita el número de instancias de un objeto en particular a una sola. Esta instancia única se llama el singleton.

  • define getInstance () que devuelve la instancia única.
  • responsable de crear y administrar el objeto de instancia.

El objeto Singleton se implementa como un función anónima inmediata. La función se ejecuta inmediatamente envolviéndola entre corchetes seguida de dos corchetes adicionales. Se llama anónimo porque no tiene nombre.

Programa de muestra,

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()
 1
Author: Mohideen ibn Mohammed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-18 07:35:32

Aquí está el ejemplo simple para explicar el patrón singleton en java script.

 var Singleton=(function(){
      var instance;
      var init=function(){
           return {
             display:function(){
             alert("This is a Singleton patern demo");
              }
            };
           }; 
            return {
              getInstance:function(){
                   if(!instance){
                     alert("Singleton check");
                      instance=init();
                       }
               return instance;
             }
         };

    })();

   // In this call first display alert("Singleton check")
  // and then alert("This is a Singleton patern demo");
  // It means one object is created

    var inst=Singleton.getInstance();
    inst.display();

    // In this call only display alert("This is a Singleton patern demo")
   //  it means second time new object is not created, 
   //  it uses the already created object 

    var inst1=Singleton.getInstance();
    inst1.display();
 1
Author: Sheo Dayal Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-24 17:20:53

Me gusta usar una combinación de Singleton con el patrón de módulo, ramificación de tiempo de inicio con una comprobación NS Global, envuelta dentro de un cierre. En un caso en el que el entorno no va a cambiar después de la inicialización del singleton; el uso de un objeto-literal inmediatamente invocado para devolver un módulo lleno de utilidades que persistirá durante algún tiempo debería estar bien. No estoy pasando ninguna dependencia, solo invocando los singletons dentro de su pequeño mundo - el único objetivo es para: crear un módulo de utilidades para el enlace / desbobinado de eventos (los cambios de orientación / orientación del dispositivo también podrían funcionar en este caso).

window.onload = ( function( _w ) {
            console.log.apply( console, ['it', 'is', 'on'] );
            ( {
                globalNS : function() {
                    var nameSpaces = ["utils", "eventUtils"],
                        nsLength = nameSpaces.length,
                        possibleNS = null;

                    outerLoop:
                    for ( var i = 0; i < nsLength; i++ ) {
                        if ( !window[nameSpaces[i]] ) {
                            window[nameSpaces[i]] = this.utils;
                            break outerLoop;
                        };
                    };
                },
                utils : {
                    addListener : null,
                    removeListener : null
                },
                listenerTypes : {
                    addEvent : function( el, type, fn ) {
                        el.addEventListener( type, fn, false );
                    },
                    removeEvent : function( el, type, fn ) {
                        el.removeEventListener( type, fn, false );
                    },
                    attachEvent : function( el, type, fn ) {
                        el.attachEvent( 'on'+type, fn );
                    },
                    detatchEvent : function( el, type, fn ) {
                        el.detachEvent( 'on'+type, fn );
                    }
                },
                buildUtils : function() {
                    if ( typeof window.addEventListener === 'function' ) {
                        this.utils.addListener = this.listenerTypes.addEvent;
                        this.utils.removeListener = this.listenerTypes.removeEvent;
                    } else {
                        this.utils.attachEvent = this.listenerTypes.attachEvent;
                        this.utils.removeListener = this.listenerTypes.detatchEvent;
                    };
                    this.globalNS();
                },
                init : function() {
                    this.buildUtils();
                }
            } ).init();
        }( window ) );
 0
Author: WHill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-23 18:57:55

No dijiste "en el navegador". De lo contrario, puede utilizar módulos NodeJS. Estos son los mismos para cada require llamada. Ejemplo básico:

El contenido de foo.js:

const circle = require('./circle.js');
console.log( `The area of a circle of radius 4 is ${circle.area(4)}`);

El contenido del círculo.js:

const PI = Math.PI;

exports.area = (r) => PI * r * r;

exports.circumference = (r) => 2 * PI * r;

Tenga en cuenta que no puede acceder a circle.PI, ya que no se exporta.

Si bien esto no funciona en el navegador, es simple y limpio.

 0
Author: serv-inc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-22 21:09:16

La clave principal es comprender la importancia del cierre detrás this.So propiedad incluso dentro de la función interior será privado con la ayuda de cierre.

Var Singleton = función () { instancia var;

 function init() {

    function privateMethod() {
        console.log("private via closure");
    }

    var privateVariable = "Private Property";

    var privateRandomNumber = Math.random();// this also private

    return {
        getRandomNumber: function () {  // access via getter in init call
            return privateRandomNumber;
        }

    };

};

return {
    getInstance: function () {

        if (!instance) {
            instance = init();
        }

        return instance;
    }

};

};

 0
Author: Siddhartha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-06 19:14:14

Singleton en javascript se logra usando patrón de módulo y cierres. A continuación se muestra el código que se explica por sí mismo-

// 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. 
 0
Author: user2756335,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-23 13:11:59

Creo que esta es la forma más simple/limpia e intuitiva, aunque requiere ES7:

export default class Singleton {

  static instance;

  constructor(){
    if(instance){
      return instance;
    }

    this.state = "duke";
    this.instance = this;
  }

}

El código fuente es de: adam-bien.com

 0
Author: Alt Eisen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-25 03:50:13