Najprostszy/najczystszy sposób implementacji Singletona w JavaScript?

Jaki jest najprostszy/najczystszy sposób implementacji wzorca Singletona w JavaScript?

Author: RzR, 2009-09-26

30 answers

Myślę, że najprostszym sposobem jest zadeklarowanie prostego obiektu literalnie:

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

Jeśli chcesz mieć prywatnych członków na swojej instancji singleton, możesz zrobić coś takiego:

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

  function privateMethod () {
    // ...
  }

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

To się nazywa wzór modułu, zasadniczo pozwala na hermetyzację prywatnych członków na obiekcie, korzystając z użycia 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/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-25 20:15:48

Myślę, że najczystsze podejście to coś w stylu:

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

Następnie możesz wywołać funkcję jako

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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-18 23:39:07

Nie jestem pewien, czy Zgadzam się ze wzorem modułu używanym jako zamiennik wzoru Singletona. Często widziałem singletony używane i nadużywane w miejscach, gdzie są całkowicie niepotrzebne, i jestem pewien, że wzór modułu wypełnia wiele luk, gdzie programiści w przeciwnym razie używaliby Singletona, jednak wzór modułu to, a nie singleton.

Wzór modułu:

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

Wszystko zainicjalizowane we wzorze modułu dzieje się, gdy Foo jest zadeklarowane. Dodatkowo moduł wzorzec może być użyty do zainicjowania konstruktora, który następnie może być wielokrotnie inicjowany. Chociaż wzorzec modułu jest właściwym narzędziem dla wielu zadań, nie jest odpowiednikiem Singletona.

Wzór Singletona:

krótka forma
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();
}
long form, using module pattern
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;
}());

W obu wersjach wzoru Singletona, który podałem, sam konstruktor może być użyty jako accessor:

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

Jeśli nie czujesz się komfortowo używając konstruktor w ten sposób możesz wyrzucić błąd w instrukcji if (instance) i trzymać się długiego formularza:

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

Powinienem również wspomnieć, że wzór Singletona dobrze pasuje do niejawnego wzoru funkcji konstruktora:

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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-09 00:20:28

Jest więcej niż jeden sposób na oskórowanie kota:) w zależności od gustu lub specyficznej potrzeby można zastosować dowolne z proponowanych rozwiązań. Osobiście korzystam z pierwszego rozwiązania CMS, gdy jest to możliwe (gdy nie potrzebujesz prywatności). Ponieważ pytanie było najprostsze i najczystsze, to jest zwycięzca. Albo nawet:

var myInstance = {}; // done!

To (cytat z mojego bloga)...

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

Nie ma większego sensu (mój przykład na blogu też nie ma), ponieważ nie potrzebuje żadnych prywatnych varów, więc jest to dość to samo co:

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/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-28 01:04:55

Odrzucam moją odpowiedź, patrz moja druga .

Zazwyczaj wzorzec modułu (patrz odpowiedź CMS), który nie jest wzorcem Singletona, jest wystarczająco dobry. Jednak jedną z cech Singletona jest to, że jego inicjalizacja jest opóźniona do momentu, gdy potrzebny jest obiekt. Module pattern nie posiada tej funkcji.

Moja propozycja (CoffeeScript):

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

Który skompilował to w JavaScript:

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

Wtedy mogę wykonać następujące czynności:

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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:05

Mam ten przykład z wzorców JavaScript Twórz lepsze aplikacje dzięki kodowaniu i wzorcom projektowym 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
        };
    };
}());

I możesz sprawdzić ten przykład, wykonując następujący przypadek testowy:

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

To podejście przechodzi wszystkie przypadki testowe, podczas gdy prywatna statyczna implementacja zawiedzie, gdy używane jest rozszerzenie prototypu (można to naprawić, ale będzie nie być prostym), a Publiczna implementacja statyczna mniej wskazana ze względu na instancję jest wystawiona na publiczne działanie.

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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-21 06:54:35

Krótka odpowiedź:

Ponieważ nieblokująca natura JavaScript, Singletony w JavaScript są naprawdę brzydkie w użyciu. Zmienne globalne dają jedną instancję przez całą aplikację również bez wszystkich tych wywołań zwrotnych, wzór modułu delikatnie ukrywa wewnętrzne za interfejsem. Zobacz odpowiedź @CMS.

Ale skoro chciałeś Singletona...]}
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);
    }
  };

};

Użycie:

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

Wyjaśnienie:

Singletony dają Ci więcej niż jedną instancję przez całą aplikację: ich inicjalizacja jest opóźniona do pierwszego użycia. Jest to naprawdę duża rzecz, gdy masz do czynienia z obiektami, których inicjalizacja jest kosztowna. Kosztowne zwykle oznacza I/O, a w JavaScript I / o zawsze oznacza wywołania zwrotne.

Nie ufaj odpowiedziom, które dają Ci interfejs jak instance = singleton.getInstance(), wszystkie one nie mają sensu.

Jeśli nie wywołują wywołania zwrotnego, gdy instancja jest gotowa, to nie będą działać, gdy inicjalizator wykonuje I / O.

Tak, wywołania zawsze wyglądają brzydiej niż funkcja wywołanie, które natychmiast zwraca instancję obiektu. Ale znowu: kiedy robisz I / O, wywołania zwrotne są obowiązkowe. Jeśli nie chcesz wykonywać żadnych operacji wejścia / Wyjścia, instancjacja jest na tyle tania, aby zrobić to przy starcie programu.

Przykład 1, cheap initializer:

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

Przykład 2, inicjalizacja za pomocą I/O:

W tym przykładzie setTimeout udaje jakąś kosztowną operację wejścia/Wyjścia. To ilustruje, dlaczego singletony w JavaScript naprawdę potrzebują wywołań zwrotnych.

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/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-19 09:01:41

Myślę, że znalazłem najczystszy sposób na programowanie w JavaScript, ale będziesz potrzebował trochę wyobraźni. Pomysł zaczerpnąłem z techniki pracy w książce "javascript the good parts".

Zamiast używać nowego słowa kluczowego, możesz utworzyć klasę taką jak:

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

Możesz utworzyć instancję powyższego obiektu, mówiąc:

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

Teraz z tą metodą pracy możesz utworzyć singleton w ten sposób:

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

}();

Teraz możesz uzyskać swoją instancję przez wywołanie

var obj = ClassSingleton.getInstance();

Myślę, że jest to najbardziej schludny sposób, ponieważ kompletna "Klasa" nie jest nawet dostępna.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-02 12:18:36

@CMS i @zzzzBov Dali wspaniałe odpowiedzi, ale po prostu dodać własną interpretację opartą na moim przejściu do ciężkiego węzła.js development z PHP / Zend Framework, gdzie wzorce Singletona były powszechne.

Poniższy, udokumentowany komentarzem kod opiera się na następujących wymaganiach:

  • można utworzyć instancję tylko jednej instancji obiektu function
  • instancja nie jest publicznie dostępna i może być dostępna tylko za pośrednictwem publicznej metoda
  • konstruktor nie jest publicznie dostępny i może być utworzony tylko wtedy, gdy nie ma jeszcze dostępnej instancji
  • deklaracja konstruktora musi umożliwiać modyfikację łańcucha prototypów. Pozwala to konstruktorowi dziedziczyć po innych prototypach i oferować metody" publiczne " dla instancji

Mój kod jest bardzo podobny do @zzzzBov ' s z tym wyjątkiem, że dodałem łańcuch prototypów do konstruktora i więcej komentarzy, które powinny pomóc tym, którzy pochodzą z PHP lub podobny język tłumaczą tradycyjny OOP na Javascripts prototypowy charakter. Może nie jest "najprostszy" , ale uważam, że jest najbardziej właściwy.

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

Zauważ, że technicznie, samo-wykonująca się funkcja anonimowa sama jest Singletonem, co ładnie pokazano w kodzie dostarczonym przez @CMS. Jedynym haczykiem jest to, że nie jest możliwe zmodyfikowanie łańcucha prototypów konstruktora, gdy sam konstruktor jest anonimowy.

Należy pamiętać, że do Javascript, pojęcia "publiczny " i" prywatny " nie mają zastosowania tak jak w PHP czy Javie. Ale osiągnęliśmy ten sam efekt, wykorzystując Zasady Javascript dotyczące dostępności zakresu funkcjonalnego.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-16 21:38:46

Nie wiem dlaczego nikt o tym nie wspomniał, ale można po prostu zrobić:

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/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-22 03:15:30

W 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-12 19:53:47

Najjaśniejszą odpowiedzią powinna być ta z książki Learning JavaScript Design Patterns autorstwa 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-10 07:28:22

Czy mogę włożyć moje 5 monet? Mam funkcję konstruktora, np.

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

To, co muszę zrobić, to po prostu każdy obiekt stworzony przez ten CF będzie taki sam.

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

Test

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/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-03 07:39:02

W node v6

class Foo {
  constructor(msg) {

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

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

Testujemy:

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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-26 08:53:54

Znalazłem następujący najprostszy wzór Singletona, ponieważ użycie nowego operatora sprawia, że ten jest natychmiast dostępny w funkcji, eliminując potrzebę zwracania obiektu literalnie:

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/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 05:40:47

Potrzebowałem kilku singletonów z:

  • leniwa inicjalizacja
  • parametry początkowe

I tak to wymyśliłem:

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 []

  • Użyłem obiektu window w funkcji, ale mogłem przekazać w parametrze, aby utworzyć własny zakres

  • Parametry Name i construct są tylko ciągiem znaków do działania window [], ale z niektórymi proste sprawdzanie typu, window.name i okno.możliwe są również konstrukcje.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-29 12:17:55

Co w tym złego?

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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-04 02:40:48

Może w ten sposób, po prostu upewnij się, że klasa nie może być nowa.

Przez to możesz użyć op instanceof, Możesz również użyć łańcucha prototypów do dziedziczenia klasy, jest to zwykła Klasa, ale nie możesz jej zmienić, jeśli chcesz uzyskać instancję, użyj 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();

Jeśli nie chcesz ujawnić członka instance, po prostu Zakończ to.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-29 12:01:48

Poniżej znajduje się fragment z mojego spaceru po implementacji wzoru Singletona. Przyszło mi to do głowy podczas wywiadu i poczułem, że powinienem to gdzieś uchwycić.

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

To samo znajdziesz na mojej stronie gist

 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/doraprojects.net/template/agent.layouts/content.php on line 54
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/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-23 22:43:52

Czy to nie singleton?

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/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-24 13:29:39

Możesz to zrobić za pomocą dekoratorów, jak w poniższym przykładzie dla maszynopisu:

class YourClass {

    @Singleton static singleton() {}

}

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

Potem używasz swojego Singletona w ten sposób:

var myInstance = YourClass.singleton();

W momencie pisania tego tekstu, dekoratory nie są łatwo dostępne w silnikach JavaScript. Musisz upewnić się, że środowisko uruchomieniowe JavaScript ma włączone dekoratory lub używać kompilatorów, takich jak Babel i TypeScript.

Zauważ również, że instancja Singletona jest tworzona "leniwie", tzn. jest tworzona tylko wtedy, gdy użyjesz jej po raz pierwszy.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-26 11:22:24

Wzór modułu: w "bardziej czytelnym stylu". Możesz łatwo zobaczyć, które metody są publiczne, a które prywatne

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");

Teraz możesz używać takich metod jak

Moduł.method2 (); / / - > wywołuję prywatną metodę nad publicznym alertem metody("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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-07 16:33:24

Singleton:

Upewnij się, że klasa ma tylko jedną instancję i zapewnij globalny punkt dostępu do niej.

Wzór Singletona ogranicza liczbę instancji danego obiektu do tylko jednego. Ta pojedyncza instancja nazywa się singleton.

  • definiuje metodę getInstance (), która zwraca unikalną instancję.
  • odpowiedzialny za tworzenie i zarządzanie obiektem instancji.

Obiekt Singleton jest zaimplementowany jako natychmiastowa funkcja anonimowa. Funkcja wykonuje się natychmiast, owijając ją w nawiasy, a następnie w dwa dodatkowe nawiasy. Nazywa się anonymous, ponieważ nie ma nazwy.

Przykładowy 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()
 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-18 07:35:32

Oto prosty przykład do wyjaśnienia wzorca Singletona w 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-24 17:20:53

Lubię używać kombinacji Singletona z modułem, rozgałęziania w czasie inicjalnym z globalną kontrolą NS, owiniętą w Zamknięcie. W przypadku, gdy środowisko nie ulegnie zmianie po inicjalizacji Singletona; użycie natychmiast wywołanego obiektu-dosłownego do zwrócenia modułu pełnego narzędzi, które będą trwać przez pewien czas, powinno być w porządku. Nie przekazuję żadnych zależności, tylko powołuję się na singletony w ich własnym małym świecie - jedynym celem jest aby: utworzyć moduł narzędzi do wiązania / odwijania zdarzeń(zmiany orientacji / orientacji urządzenia mogą również działać w tym przypadku).

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/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-23 18:57:55

Nie powiedziałeś "w przeglądarce". W przeciwnym razie możesz użyć modułów NodeJS . Te są takie same dla każdego require wywołania . Przykład podstawowy:

Zawartość foo.js:

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

Zawartość koła.js:

const PI = Math.PI;

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

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

Zauważ, że nie możesz uzyskać dostępu do circle.PI, ponieważ nie jest eksportowany.

Chociaż nie działa to w przeglądarce, jest proste i czyste.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 21:09:16

Głównym kluczem jest zrozumienie znaczenia zamknięcia za this.So własność nawet wewnątrz wewnętrznej funkcji będzie prywatna za pomocą zamknięcia.

Var Singleton = funkcja () { var instance;

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-06 19:14:14

Singleton w javascript jest osiągany za pomocą wzorca modułu i zamknięć. Poniżej znajduje się kod, który jest dość oczywisty -

// 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-23 13:11:59

Uważam, że jest to najprostszy/najczystszy i najbardziej intuicyjny sposób, chociaż wymaga ES7:

export default class Singleton {

  static instance;

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

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

}

Kod źródłowy pochodzi z: 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-25 03:50:13