De eenvoudigste/schoonste manier om een singleton in JavaScript te implementeren

Wat is de eenvoudigste/schoonste manier om het singleton-patroonin JavaScript te implementeren?


Antwoord 1, autoriteit 100%

Ik denk dat de gemakkelijkste manier is om een eenvoudig object letterlijk te declareren:

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

Als je privéleden op je singleton-instantie wilt, kun je zoiets als dit doen:

var myInstance = (function() {
  var privateVar = '';
  function privateMethod () {
    // ...
  }
  return { // public interface
    publicMethod1: function () {
      // All private members are accessible here
    },
    publicMethod2: function () {
    }
  };
})();

Dit wordt het modulepatroon, en het stelt je in feite in staat om privé-leden op een object in te kapselen, door gebruik te maken van het gebruik van sluitingen.

Als u de wijziging van het singleton-object wilt voorkomen, kunt u het bevriezenmet behulp van de ES5 Object.freeze-methode.

Dat maakt het object onveranderlijk, waardoor elke wijziging aan de structuur en waarden wordt voorkomen.

Als je ES6 gebruikt, kun je heel gemakkelijk een singleton vertegenwoordigen met behulp van ES Modules, en je kunt zelfs private statebehouden door variabelen te declareren in de module bereik:

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

Vervolgens kunt u eenvoudig het singleton-object importeren om het te gebruiken:

import myInstance from './my-singleton.js'
// ...

Antwoord 2, autoriteit 55%

Ik denk dat de schoonste aanpak zoiets is als:

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

Daarna kunt u de functie aanroepen als

var test = SingletonFactory.getInstance();

Antwoord 3, autoriteit 32%

Ik weet niet zeker of ik het eens ben met het modulepatroon dat wordt gebruikt als vervanging voor een singletonpatroon. Ik heb vaak gezien dat singletons worden gebruikt en misbruikt op plaatsen waar ze totaal niet nodig zijn, en ik weet zeker dat het modulepatroon veel gaten opvult waar programmeurs anders een singleton zouden gebruiken. Het modulepatroon is echter geeneen singleton.

Modulepatroon:

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

Alles geïnitialiseerd in het modulepatroon gebeurt wanneer Foowordt gedeclareerd. Bovendien kan het modulepatroon worden gebruikt om een constructor te initialiseren, die vervolgens meerdere keren kan worden geïnstantieerd. Hoewel het modulepatroon het juiste hulpmiddel is voor veel taken, is het niet hetzelfde als een eenling.

Eenvoudig patroon:

kort formulier

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

lange vorm, met modulepatroon

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

In beide versies van het singleton-patroon dat ik heb verstrekt, kan de constructor zelf als accessor worden gebruikt:

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

Als u zich niet op uw gemak voelt bij het gebruik van de constructor op deze manier, kunt u een fout maken in de if (instance)-instructie en vasthouden aan het gebruik van de lange vorm:

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

Ik moet ook vermelden dat het singletonpatroon goed past bij het impliciete constructorfunctiepatroon:

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

Antwoord 4, autoriteit 11%

In ES6is de juiste manier om dit te doen:

class MyClass {
  constructor() {
    if (MyClass._instance) {
      throw new Error("Singleton classes can't be instantiated more than once.")
    }
    MyClass._instance = this;
    // ... Your rest of the constructor code goes after this
  }
}
var instanceOne = new MyClass() // Executes succesfully
var instanceTwo = new MyClass() // Throws error

5, Autoriteit 6%

in ecmascript & nbsp; 2015 (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

6, Autoriteit 4%

De volgende werken in Node.js versie 6:

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

We testen:

const f = new Foo('blah');
const d = new Foo('nope');
console.log(f); // => Foo { msg: 'blah' }
console.log(d); // => Foo { msg: 'blah' }

7, Autoriteit 2%

Er is meer dan één manier om een ​​kat te hinderen 🙂 Afhankelijk van uw smaak of specifieke behoefte kunt u een van de voorgestelde oplossingen toepassen. Ik ga persoonlijk voor Christian C. Salvadó’s eerste oplossing waar mogelijk (wanneer u geen privacy nodig hebt).

Sinds de vraag was over het eenvoudigste en schoonste, is dat de winnaar. Of zelfs:

var myInstance = {}; // Done!

dit (citaat uit mijn blog) …

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

Maakt niet veel logisch (mijn blogvoorbeeld niet) omdat het geen privévariabelen nodig heeft, dus het is vrijwel hetzelfde als:

var SingletonClass = {
    myFunction: function () {
        // Do stuff
    },
    instance: 1
}

8, Autoriteit 2%

Ik verwijder mijn antwoord, zie mijn andere .

Meestal het modulepatroon (zie Christian C. Salvadó’s antwoord ), dat is niet Het Singleton-patroon is goed genoeg. Een van de kenmerken van de Singleton is echter dat de initialisatie van zijn initialisatie wordt uitgesteld totdat het object nodig is. Het modulepatroon mist deze functie.

Mijn propositie (Coffeescript):

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

die hierop samengesteld in JavaScript:

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

Dan kan ik het volgende doen:

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

Antwoord 9, autoriteit 2%

Ik heb dit voorbeeld van de *JavaScript-patronen
Bouw betere toepassingen met codering en ontwerppatronen
boek (door Stoyan Stefanov). Als u een eenvoudige implementatieklasse nodig heeft, zoals een singleton-object, kunt u een onmiddellijke functie gebruiken zoals in het volgende:

var ClassName;
(function() {
    var instance;
    ClassName = function ClassName() {
        // If the private instance variable is already initialized, return a reference
        if(instance) {
            return instance;
        }
        // If the instance is not created, save a pointer of the original reference
        // to the private instance variable.
        instance = this;
        // All constructor initialization will be here
        // i.e.:
        this.someProperty = 0;
        this.someMethod = function() {
            // Some action here
        };
    };
}());

En u kunt dit voorbeeld controleren door de volgende testcase te volgen:

// Extending defined class like singleton object using the new prototype property
ClassName.prototype.nothing = true;
var obj_1 = new ClassName();
// Extending the defined class like a singleton object using the new prototype property
ClassName.prototype.everything = true;
var obj_2 = new ClassName();
// Testing makes these two objects point to the same instance
console.log(obj_1 === obj_2); // Result is true, and it points to the same instance object
// All prototype properties 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 are defined inside of the constructor
console.log(obj_1.someProperty); // Outputs 0
console.log(obj_2.someProperty); // Outputs 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

Deze aanpak doorstaat alle testgevallen, terwijl een private statische implementatie zal mislukken wanneer een prototype-extensie wordt gebruikt (het kan worden opgelost, maar het zal niet eenvoudig zijn) en een openbare statische implementatie die minder aan te raden is omdat een instantie wordt blootgesteld aan de openbaar.

jsFiddly-demo.


Antwoord 10, autoriteit 2%

Kort antwoord:

Vanwege het niet-blokkerende karakter van JavaScript zijn singletons in JavaScript erg lelijk in gebruik. Globale variabelen geven je ook één instantie door de hele applicatie zonder al deze callbacks, en het modulepatroon verbergt zachtjes de binnenkant achter de interface. Zie antwoord van Christian C. Salvadó.

Maar aangezien je een eenling wilde…

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

Gebruik:

var singletonInitializer = function(instanceReady) {
  var preparedObject = {property: 'value'};
  // Calling instanceReady notifies the singleton that the instance is ready to use
  instanceReady(preparedObject);
}
var s = singleton(singletonInitializer);
// Get the instance and use it
s(function(instance) {
  instance.doSomething();
});

Uitleg:

Singletons geven je meer dan één instantie door de hele applicatie: hun initialisatie wordt uitgesteld tot het eerste gebruik. Dit is echt een groot ding als je te maken hebt met objecten waarvan de initialisatie duur is. Duur betekent meestal I/O en in JavaScript betekent I/O altijd callbacks.

Vertrouw geen antwoorden die u een interface geven zoals instance = singleton.getInstance(), ze missen allemaal het punt.

Als ze geen callback aannemen om te worden uitgevoerd wanneer een instantie gereed is, werken ze niet wanneer de initializer I/O uitvoert.

Ja, callbacks zien er altijd lelijker uit dan een functieaanroep die onmiddellijk een objectinstantie retourneert. Maar nogmaals: als je I/O doet, zijn callbacks verplicht. Als u geen I/O wilt doen, is instantiëren goedkoop genoeg om dit bij het starten van het programma te doen.

Voorbeeld 1, goedkope 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);
});

Voorbeeld 2, initialisatie met I/O:

In dit voorbeeld vervalst setTimeouteen dure I/O-bewerking. Dit illustreert waarom singletons in JavaScript echt callbacks nodig hebben.

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

Antwoord 11, autoriteit 2%

De eenvoudigste/schoonste betekent voor mij ook gewoon te begrijpen en geen toeters & fluitjes zoals veel besproken in de Java-versie van de discussie:

Wat is een efficiënte manier om een singleton-patroon in Java te implementeren?

Het antwoord dat daar vanuit mijn oogpunt het eenvoudigst/schoonst zou passen, is:

Jonathan’s antwoord op Wat is een efficiënte manier om een singleton-patroon in Java te implementeren?

En het kan slechts gedeeltelijk worden vertaald naar JavaScript. Enkele verschillen in JavaScript zijn:

  • constructors kunnen niet privé zijn
  • Klassen mogen geen gedeclareerde velden hebben

Maar gezien de nieuwste ECMA-syntaxis, is het mogelijk om dichtbij te komen met:

Singleton-patroon als voorbeeld van een JavaScript-klasse

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

voorbeeld gebruik

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

Voorbeeldresultaat

DefaultField1
DefaultField2

12

Christian C. Salvadó’s en ZZZZBOV’s antwoord hebben allebei Gegeven prachtige antwoorden, maar om mijn eigen interpretatie toe te voegen, gebaseerd op mijn ontwikkeling van het zware knooppunt. Jsjs-ontwikkeling van PHP / Zend-raamwerk waarbij Singleton-patronen gebruikelijk waren.

De volgende, opmerkingen gedocumenteerde code is gebaseerd op de volgende vereisten:

  • één en slechts één exemplaar van het functieobject kan worden geïnstantiek
  • Het exemplaar is niet openbaar beschikbaar en mag alleen via een openbare methode worden geopend
  • De constructeur is niet openbaar beschikbaar en mag alleen worden geïnstantieerd als er nog geen instantie beschikbaar is
  • De verklaring van de constructor moet zijn prototype keten toestaan ​​te wijzigen. Hierdoor kan de constructeur het erven van andere prototypen en bieden “openbare” methoden voor het exemplaar

Mijn code lijkt erg op het antwoord van zzzzBov, behalve dat ik een prototypeketen aan de constructor heb toegevoegd en meer opmerkingen die degenen die van PHP of een vergelijkbare taal komen, moeten helpen om traditionele OOP te vertalen naar de prototypische aard van JavaScript. Het is misschien niet de “eenvoudigste”, maar ik geloof dat het de meest geschikte is.

// Declare 'Singleton' as the returned value of a self-executing anonymous function
var Singleton = (function () {
    "use strict";
    // 'instance' and 'constructor' should not be available 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'

Merk op dat technisch gezien de zelfuitvoerende anonieme functie zelf een eenling is, zoals mooi wordt aangetoond in de code die is geleverd door Christian C. Salvadó. Het enige nadeel hier is dat het niet mogelijk is om de prototypeketen van de constructor te wijzigen wanneer de constructor zelf anoniem is.

Houd er rekening mee dat voor JavaScript de concepten ‘openbaar’ en ‘privé’ niet van toepassing zijn zoals in PHP of Java. Maar we hebben hetzelfde effect bereikt door gebruik te maken van de JavaScript-regels voor de beschikbaarheid van functionele scopes.


Antwoord 13

Je zou gewoon kunnen doen:

var singleton = new (function() {
  var bar = 123
  this.foo = function() {
    // Whatever
  }
})()

Antwoord 14

Ik denk dat ik de schoonste manier heb gevonden om in JavaScript te programmeren, maar je hebt wat fantasie nodig. Ik kreeg dit idee van een werktechniek in het boek JavaScript: The Good Parts.

In plaats van het nieuwezoekwoord te gebruiken, kunt u een les als volgt maken:

function Class()
{
    var obj = {}; // Could also be used for inheritance if you don't start with an empty object.
    var privateVar;
    obj.publicVar;
    obj.publicMethod = publicMethod;
    function publicMethod(){}
    function privateMethod(){}
    return obj;
}

Je kunt het bovenstaande object instantiëren door te zeggen:

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

Met deze werkmethode in gedachten, zou je een singleton als volgt kunnen maken:

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

Nu kunt u uw exemplaar verkrijgen door te bellen

var obj = ClassSingleton.getInstance();

Ik denk dat dit de handigste manier is, aangezien de volledige “Klasse” niet eens toegankelijk is.


Antwoord 15

Het duidelijkste antwoord zou dit antwoord moeten zijn uit het boek Learning JavaScript Design Patternsvan 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 = "I'm 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;
    }
  };
})();

Antwoord 16

Dit zou moeten werken:

function Klass() {
   var instance = this;
   Klass = function () { return instance; }
}

Antwoord 17

Ik geloof dat dit de eenvoudigste/schoonste en meest intuïtieve manier is, hoewel het ECMAScript  2016(ES7):

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

De broncode is van: adam-bien.com


Antwoord 18

Voor mij is de schoonste manier om dit te doen:

const singleton = new class {
    name = "foo"
    constructor() {
        console.log(`Singleton ${this.name} constructed`)
    }
}

Met deze syntaxis weet je zeker dat je singleton uniek is en blijft. Je kunt ook genieten van de zoetheid van de klassensyntaxis en thisgebruiken zoals verwacht.

(Merk op dat klassevelden node v12+ of een moderne browser vereisen.)


Antwoord 19

Als je klassen wilt gebruiken:

class Singleton {
  constructor(name, age) {
    this.name = name;
    this.age = age;
    if(this.constructor.instance)
      return this.constructor.instance;
    this.constructor.instance = this;
  }
}
let x = new Singleton('s', 1);
let y = new Singleton('k', 2);

Uitvoer voor het bovenstaande is:

console.log(x.name, x.age, y.name, y.age) // s 1 s 1

Een andere manier om Singleton te schrijven met de functie

function AnotherSingleton (name,age) {
  this.name = name;
  this.age = age;
  if(this.constructor.instance)
    return this.constructor.instance;
  this.constructor.instance = this;
}
let a = new AnotherSingleton('s', 1);
let b = new AnotherSingleton('k', 2);

Uitvoer voor het bovenstaande is:

console.log(a.name, a.age, b.name, b.age) // s 1 s 1

Antwoord 20

Hier volgt het fragment uit mijn walkthrough om een singleton-patroon te implementeren. Dit kwam bij me op tijdens een sollicitatiegesprek en ik vond dat ik dit ergens moest vastleggen.

/*************************************************
 *     SINGLETON PATTERN IMPLEMENTATION          *
 *************************************************/
// Since there aren't any 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 the 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 give 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
*******************************************************************/

hetzelfde is te vinden op mijn gistpagina .


21

Mijn twee centen: ik heb een constructormunctie (CF), bijvoorbeeld,

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

Ik heb net elk object nodig dat door deze CF is gemaakt om hetzelfde te zijn.

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

Test

var x1 = new X();
var x2 = new X();
console.log(x1 === x2)

22

Hier is een eenvoudig voorbeeld om het Singleton-patroon in JavaScript uit te leggen.

var Singleton = (function() {
    var instance;
    var init = function() {
        return {
            display:function() {
                alert("This is a singleton pattern 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 pattern demo");
// It means one object is created
var inst = Singleton.getInstance();
inst.display();
// In this call only display alert("This is a singleton pattern demo")
// it means second time new object is not created,
// it uses the already created object
var inst1 = Singleton.getInstance();
inst1.display();

23

function Once() {
    return this.constructor.instance || (this.constructor.instance = this);
}
function Application(name) {
    let app = Once.call(this);
    app.name = name;
    return app;
}

Als u in klassen bent:

class Once {
    constructor() {
        return this.constructor.instance || (this.constructor.instance = this);
    }
}
class Application extends Once {
    constructor(name) {
        super();
        this.name = name;
    }
}

Test:

console.log(new Once() === new Once());
let app1 = new Application('Foobar');
let app2 = new Application('Barfoo');
console.log(app1 === app2);
console.log(app1.name); // Barfoo

24

Ik had verschillende singletons nodig met:

  • luie initialisatie
  • eerste parameters

En dus was dit waar ik bedacht:

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;
}
  • argsMOET ARRAY VOOR HET WERKEN, dus als u lege variabelen hebt, geeft u gewoon door []

  • Ik heb het venster in de functie gebruikt, maar ik had een parameter kunnen passeren om mijn eigen scope

    te maken

  • name en construct parameters zijn alleen String om window[] te laten werken, maar met wat simpele typecontrole zijn window.nameen window.constructook mogelijk.


Antwoord 25

Modulepatroon: in “leesbare stijl”. U kunt eenvoudig zien welke methoden openbaar zijn en welke privé

var module = (function(_name){
   /* Local Methods & Values */
   var _local = {
      name : _name,
      flags : {
        init : false
      }
   }
   function init(){
     _local.flags.init = true;
   }
   function imaprivatemethod(){
     alert("Hi, I'm a private method");
   }
   /* Public Methods & variables */
   var $r = {}; // This object will hold all public methods.
   $r.methdo1 = function(){
       console.log("method1 calls 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 the init method
   return $r; // Returning all public methods
})("module");

Je kunt nu openbare methoden gebruiken, zoals

module.methode2(); // -> Ik roep een privémethode aan via een openbare methodewaarschuwing (“Hallo, ik ben een privémethode”)

http://jsfiddle.net/ncubica/xMwS9/


Antwoord 26

Een andere manier – zorg er gewoon voor dat de klas niet opnieuw kan.

Hierdoor kunt u de instanceofop. U kunt ook de prototypeketen gebruiken om de klasse te erven. Het is een gewone les, maar je kunt hem niet nieuw. Als u de instantie wilt ophalen, gebruikt u gewoon 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');}
}
// Initialise the instance
new CA();
// Test here
var c = CA.getInstance()
c.func();
console.assert(c instanceof CA)
// This will fail
var b = new CA();

Als je het instance-lid niet openbaar wilt maken, plaats het dan gewoon in een sluiting.


Antwoord 27

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,
    // and then pad zeroes to the code point
    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

Antwoord 28

Dit is ook een eenling:

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

Antwoord 29

Je kunt het doen met decorateurs zoals in dit voorbeeld hieronder voor TypeScript:

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

Dan gebruik je je singleton als volgt:

var myInstance = YourClass.singleton();

Op het moment van schrijven zijn decorateurs niet direct beschikbaar in JavaScript-engines. U moet ervoor zorgen dat uw JavaScript-runtime decorateurs daadwerkelijk heeft ingeschakeld of compilers zoals Babel en TypeScript gebruiken.

Houd er rekening mee dat de singleton-instantie “lui” is gemaakt, d.w.z. dat deze alleen wordt gemaakt wanneer u deze voor de eerste keer gebruikt.

Other episodes