1. Verwenden Sie globale Variablen, um einzelne Fälle zu sparen
Dies ist der einfachste Weg, es umzusetzen
Funktion person () {this.createTime = new Date (); } var instance = new Person (); Funktion getInstance () {return Instance; }Beim Laden dieses JS wird ein Personobjekt erstellt und in der globalen Instanzvariablen gespeichert. Dieses Objekt wird jedes Mal aufgenommen, wenn es verwendet wird. Wenn Sie es noch einmal verwendet haben, das von Ihnen erstellte Objekt ist verschwendet, können wir es optimieren.
var Instance -Funktion getInstance () {if (! Instance) {Instance = new Person (); } return Instance; }Auf diese Weise wird das Objekt nur erstellt, wenn es zum ersten Mal verwendet wird.
Der Nachteil dieser Methode ist, dass die Instanz eine globale Variable ist. Wenn mehrere Personen zusammenarbeiten oder der Entwicklungszyklus relativ lang ist, ist es schwierig sicherzustellen, dass die Instanz nicht durch andere Codes geändert oder überschrieben wird. Es ist sehr wahrscheinlich, dass beim Aufrufen des Anrufs festgestellt wird, dass Instanz überhaupt kein Personobjekt ist.
Überlegen wir, ob die Verschlüsse verwendet werden, um die Instanz so zu verkapulieren, dass es keine globale Variable mehr ist, um dieses Problem zu lösen.
2. Closeure Creation -Objekt
var getInstance () {var Instance; return function () {if (! Instance) {instance = new Person (); } return Instance; }} ();Auf diese Weise ist die Instanz eingekapselt und es besteht keine Notwendigkeit, sich Sorgen um zu modifizieren.
Jetzt können Sie einen Singleton durch die GetInstance () -Funktion erhalten. Neue Frage, wenn ich ein Objekt über New Person () erstelle, bekomme ich immer noch mehrere Objekte und JavaScript kann den Konstruktor wie Java nicht berufen. Wie können wir also die mehrmals neuen Objekte zu einer Instanz machen?
3.. Statische Attribut -Cache -Instanz des Konstruktors
Schauen Sie sich zuerst den Code an
Funktion person () {// Wenn die Instanz zwischengespeichert wurde, gibt sie die zwischengespeicherte Instanz direkt zurück, wenn (typeof person.instance === 'Objekt') {return person.instance; } this.createTime = new Date (); // zwischengespeicherte Instanzperson.instance = this; gib dies zurück; }Aus dem Code können wir sehen, dass das erste Mal neu, die Bedingung von If Rets False, abfällt, das Objekt initialisieren und dann das Objekt in der statischen Eigenschaftsperson speichern.
Das zweite Mal neu, die Bedingung von If Return true, gibt die Person.instanz direkt zurück, und der initialisierte Code wird nicht heruntergefallen. Egal wie oft neu ist, das zurückgegebene Objekt ist das erste erstellte Objekt.
Die Nachteile dieser Methode entsprechen den von Method One. Person.instance ist auch ein öffentliches Eigentum und kann geändert werden.
Beziehen wir uns auf die Methode 2. Verwenden eines Verschlusses, um einen Einkapsel zu verwenden, kann das Problem lösen
4. Schreiben Sie den Konstruktor neu
Diese Methode muss Verschlüsse verwenden, aber es kann nicht so einfach sein wie Methode Zwei. Wir müssen den Konstruktor überschreiben.
Funktion person () {// zwischengespeicherte Instanz var instance = this; this.createTime = new Date (); // Schreiben Sie die Konstruktorperson = function () {return Instance; }}Das erste Mal, dass Neue genannt wird, wird der ursprüngliche Konstruktor zuerst zwischengespeichert und dann initialisiert und der Konstruktor überschrieben. Wenn der ursprüngliche Konstruktor in Zukunft neu ist, wird er niemals aufgerufen, und der Rewrite -Konstruktor kann nur aufgerufen werden, und diese Funktion gibt immer die zwischengespeicherte Instanz zurück.
Die obige Methode scheint in Ordnung zu sein, aber durch den folgenden Test können Sie das Problem finden
// Attributperson hinzufügen.Prototype.prop1 = true; var p1 = new Person (); // Nach dem Erstellen des Initialisierungsobjekts Attributperson.Prototype.Prop2 = true; var p2 = new Person (); // test console.log (p1.prop1); // Das Ergebnis ist echte Konsole.log (p2.Prop1); // Das Ergebnis ist echte Konsole.log (p1.prop2); // Das Ergebnis ist undefined Console.log (p2.Prop2); // Das Ergebnis ist undefined Console. console.log (p1.constructor === Person); // Das Ergebnis ist false console.log (p2.Constructor === Person); // Das Ergebnis ist falsch
Die erwarteten Ergebnisse sollten wahr sein.
Analysieren Sie den obigen Testcode
Person.Prototype.prop1 = true; Fügt das Prop1 -Attribut unter dem Prototyp des ursprünglichen Konstruktors hinzu und weist einen Wert zu.
Nach Ausführung von var p1 = new Person ();, der Personkonstruktor wurde umgeschrieben
Daher person.Prototype.prop2 = true; Fügt die Prop2 -Eigenschaft unter dem neuen Prototyp hinzu.
var p2 = new Person (); P2 und P1 sind tatsächlich das gleiche Objekt, dh das vom ursprünglichen Konstruktor erstellte Objekt
P1 und P2 haben also das Eigentum prop1, aber es gibt keine Eigentumsprop22
In ähnlicher Weise verweist der Konstruktor von P1 und P2 auch auf den ursprünglichen Konstruktor, und die Person ist zu diesem Zeitpunkt nicht mehr die ursprüngliche Funktion.
Um wie erwartet zu laufen, können einige Modifikationen erreicht werden
Funktion person () {// zwischengespeicherte Instanz var instance = this; // Constructor person = function () {return Instance neu schreiben; } // Die Prototyp -Attributperson.Prototype = this; // Instance = new Person (); // Die Konstruktor -Referenzinstanz zurücksetzen.Constructor = Person; // Andere Initialisierungsinstanz.CreateTime = new Date (); Rückkehrinstanz; }Führen Sie den vorherigen Testcode aus und das Ergebnis ist wahr.
5. Faules Laden:
In großen oder komplexen Projekten spielt es eine Optimierungsrolle: Komponenten, die teuer, aber selten verwendet werden, können in faule Lade -Singletons, Beispielprogramme eingewickelt werden:
/* Singleton with Private Members, step 3. */MyNamespace.Singleton = (function() { // Private members. var privateAttribute1 = false; var privateAttribute2 = [1, 2, 3]; function privateMethod1() { ... } function privateMethod2(args) { ... } return { // Public members. publicAttribute1: true, publicAttribute2: 10, PublicMethod1: function () {...}, PublicMethod2: Funktion (args) {...}};}) ();/ * Allgemeines Skelett für einen faulen Laden mit Singleton, Schritt 1. privateattribute2 = [1, 2, 3]; Skelett für ein faules Laden von Singleton, Schritt 2. */myNamespace.singleton = (function () {function Constructor () {// Alle normalen Singleton -Code geht hierher. */MyNameSpace.singleton = (function () {var UniqueInstance; // Private Attribut, das die einzelne Instanz enthält. }}}) ();6. Verwenden Sie Branch Singleton:
Der Code für eine bestimmte Umgebung kann in ein verzweigtes Beispielprogramm mit Singleton, Beispiel:
/ * SimplexHrfactory Singleton, Schritt 1. */Var simplexHrfactory = (function () {// Die drei Zweige. Var Standard = {createxHRObject: function () {return New XmlHttprequest ();}}; ActiveXObject ('msxml2.xmlhttp'); var standard = {createxhrObject: function () {neuer XMLHttprequest (); ActiveXObject('Microsoft.XMLHTTP'); } }; // To assign the branch, try each method; return whatever doesn't fail. var testObject; try { testObject = standard.createXhrObject(); return standard; // Return this if no error was thrown. } catch(e) { try { testObject = activeXNew.createXhrObject(); return activeXNew; // Return Dies wurde kein Fehler geworfen.