Mehrere häufig verwendete Objekterstellungsmodi
Erstellen Sie mit neuem Keyword
Die grundlegendste Möglichkeit, Objekte zu erstellen, ist nichts anderes als das, was die meisten Sprachen sagen: Wenn Sie keine Objekte haben, können Sie neu erhalten!
var gf = new Object (); gf.name = "tangwei"; gf.bar = "c ++";
Mit Literalen schaffen
Dies scheint wahr zu sein, aber wie können Geeks eine solch komplexe und niedrige Art wie die Definition von Variablen mögen? Als Scripting -Sprache sollte es den gleichen Stil haben wie andere Brüder, sodass die Art der Definition von Objektliteralen erscheint:
var gf = {name: "tangwei", bar: "c ++", sagen was: function () {console.log (this.name+"sad: liebe dich für immer"); }}Fabrikmodell
Tatsächlich ist dies die am häufigsten verwendete Objektdefinitionsmethode in der Realität, aber was sollte ich tun, wenn ich viele Objekte mit ähnlichen Attributen habe (es ist aufregend, darüber nachzudenken ...)? Wenn eine Definition nacheinander vorgenommen wird, wird eine große Menge Code generiert. Warum nicht eine Fabrik und Masse erstellen, produzieren unsere Objekte? Das erste aufblasbare Baby in der JavaScript -Welt. . . Nein, das "Fabrikmodell" wird geboren!
Funktion createGf (Name, Bar) {var o = new Object (); O.Name = Name; O.BAR = Bar; o.saywhat = function () {alert (this.name + "sad: liebe dich für immer"); } return o;} var gf1 = createGf ("Bingbing", "D"); var gf2 = createGf ("mimi", "a");Konstruktor
Das Werksmuster löst das Problem der Erstellung mehrerer ähnlicher Objekte, aber das Problem kommt erneut. Diese Objekte werden alle von Objekten gebildet. Wie unterscheidet man die spezifischen Arten ihrer Objekte? Zu diesem Zeitpunkt müssen wir in einen anderen Modus, den Konstruktor -Modus, wechseln:
Funktion GF (Name, Bar) {this.name = name; this.bar = bar; this.saywhat = function () {alert (this.name + "sagte: liebe dich für immer"); }} var gf1 = new gf ("vivian", "f"); var gf2 = new GF ("vivian2", "f");Hier verwenden wir einen Konstruktor, der mit Großbuchstaben beginnt, um CreateGF im obigen Beispiel zu ersetzen. Beachten Sie, dass der erste Buchstabe des Konstruktors gemäß der Konvention aktiviert werden sollte. Hier erstellen wir ein neues Objekt, dann dem neuen Objekt den Umfang des Konstruktors und rufen die Methoden im Konstruktor auf.
Mit der obigen Methode scheint nichts auszusetzen, aber wir können feststellen, dass die Saywhat -Methode im Konstruktor, die in den beiden Instanzen genannt wird, nicht die gleiche Funktionsinstanz ist:
console.log (gf1.saywhat == gf2.saywhat); //FALSCH
Das Aufrufen der gleichen Methode, aber die Erklärung verschiedener Instanzen ist eine Verschwendung von Ressourcen. Wir können die Aussage der Saywhat -Funktion außerhalb des Konstruktors optimieren:
Funktion GF (Name, Bar) {this.name = name; this.bar = bar; this.saywhat = saywhat} Funktion sagt was () {alert (this.name + "sad: liebe dich für immer");}Dies löst das Problem, die gleiche Methode -Instanz mehrmals zu definieren, aber ein neues Problem kommt erneut. Das Sprichwort, was wir definiert haben, ist eine globale Umfangsmethode, aber diese Methode kann nicht direkt aufgerufen werden, was ein bisschen widersprüchlich ist. Wie kann man ein Objekt mit einer bestimmten Einkapselung eleganter definieren? Schauen wir uns das JavaScript -Prototyp -Objektmuster an.
Prototyp -Objektmuster
Prototypobjekte verstehen
Wenn wir eine Funktion erstellen, verfügt die Funktion über ein Prototypattribut, das auf das Prototypobjekt der vom Konstruktor erstellten Funktion zeigt. In Layman's Terms sind Prototypobjekte Objekte im Speicher, die gemeinsame Eigenschaften und Methoden für andere Objekte bereitstellen.
Im Prototypenmodus müssen keine Instanzattribute im Konstruktor definiert werden, und die Attributinformationen können direkt dem Prototyp -Objekt zugeordnet werden:
Funktion gf () {gf.prototype.name = "vivian"; Gf.prototype.bar = "c ++"; Gf.prototype.saywhat = function () {alert (this.name + "sad: liebe dich für immer"); }} var gf1 = new gf (); gf1.saywhat (); var gf2 = new gf ();Der Unterschied zum Konstruktor besteht darin, dass die Eigenschaften und Methoden des neuen Objekts von allen Fällen geteilt werden können. Mit anderen Worten, GF1 und GF2 zugreifen auf die gleichen Eigenschaften und Methoden. Zusätzlich zu den zugewiesenen Attributen gibt es auch einige integrierte Attribute im Prototypobjekt. Alle Prototyp -Objekte haben ein Konstruktorattribut, bei dem es sich um einen Zeiger auf eine Funktion handelt, die das Prototyp -Attribut enthält (unabhängig davon, ob Sie es wagen, wieder um den Punkt zu gehen!). Lassen Sie uns durch ein Bild den Prozess dieser Verdrehung klar aussortieren:
Alle Objekte haben ein Prototypobjekt (Prototyp). Es gibt ein Konstruktorattribut im Prototyp -Objekt, das auf eine Funktion zeigt, die das Prototyp -Attribut enthält. Die Instanzen von GFs GF1 und GF2 enthalten beide ein internes Attribut, das auf das Prototyp -Objekt zeigt (Proto erscheint als privates Attribut im Firefox -Browser). Wenn wir in einem Objekt auf das Attribut zugreifen, werden wir zunächst fragen, ob das Instanzobjekt über dieses Attribut verfügt. Wenn nicht, werden wir weiterhin nach dem Prototypobjekt suchen.
Verwenden von Prototypobjekten
Im vorherigen Beispiel haben wir festgestellt, dass wir beim Hinzufügen von Eigenschaften zum Prototyp -Objekt zu jedem GF.Prototyp hinzugefügt werden müssen. Diese Arbeit ist sehr wiederholt. Im obigen Objekterstellungsmuster wissen wir, dass ein Objekt in Form von Literalen erstellt werden kann. Hier können wir es auch verbessern:
Funktion gf () {} gf.prototype = {name: "vivian", bar: "c ++", sagen was: function () {alert (this.name+"sad: liebe dich für immer"); }}Es gibt einen Ort, an dem wir besondere Aufmerksamkeit schenken müssen. Das Konstruktorattribut zeigt nicht mehr auf das Objekt GF, da jedes Mal, wenn eine Funktion definiert ist, gleichzeitig ein Prototypobjekt dafür erstellt wird und dieses Objekt automatisch ein neues Konstruktorattribut erhält. An diesem Ort verwenden wir GF.Prototype, um das ursprüngliche Prototyp -Objekt im Wesentlichen zu überschreiben, sodass der Konstruktor auch zum Konstruktorattribut des neuen Objekts geworden ist und nicht mehr auf GF zeigt, sondern Objekt:
var gf1 = new gf (); console.log (gf1.constructor == gf); // falseconsole.log (gf1.constructor == Objekt) // true
Im Allgemeinen wirkt sich diese subtile Änderung nicht auf uns aus. Wenn Sie jedoch über besondere Bedürfnisse für Konstruktor sind, können wir auch die Konstruktoreigenschaft von GF.Prototyp explizit angeben:
Gf.prototype = {constructor: gf, name: "vivian", bar: "c ++", sagen was: function () {alert (this.name+"sagte: liebe dich für immer"); }} var gf1 = new gf (); console.log (gf1.constructor == gf); // trueDurch ein vorläufiges Verständnis des Prototyp-Objektmusters stellten wir fest, dass alle Instanzobjekte dieselben Attribute teilen, was das grundlegende Merkmal des Prototyp-Musters ist, aber oft ist dies ein "zweischneidiges Schwert" für Entwickler. In der tatsächlichen Entwicklung sollten die Fälle, von denen wir hoffen, dass sie ihre eigenen Attribute haben sollten, was auch der Hauptgrund ist, warum nur wenige Menschen das Prototyp -Muster allein in der tatsächlichen Entwicklung verwenden.
Konstruktor- und Prototyp -Kombinationsmuster
In der tatsächlichen Entwicklung können wir Konstruktoren verwenden, um die Eigenschaften von Objekten zu definieren und Prototypen zu verwenden, um gemeinsame Eigenschaften und Methoden zu definieren, damit wir verschiedene Parameter übergeben können, um unterschiedliche Objekte zu erstellen, während wir gemeinsame Methoden und Eigenschaften haben.
Funktion GF (Name, Bar) {this.name = name; this.bar = bar;} gf.prototype = {constructor: gf, sagen was: function () {alert (this.name + "sad: liebe dich für immer"); }} var gf1 = new gf ("vivian", "f"); var gf2 = new GF ("vivian1", "c");In diesem Beispiel definieren wir die jeweiligen Eigenschaftswerte der Objekte in der Konstruktorfunktion und definieren das Konstruktorattribut und sagen, welche Funktion im Prototyp -Objekt, sodass keine Auswirkungen zwischen den Attributen GF1 und GF2 vorhanden sind. Dieses Muster ist auch die am häufigsten verwendete Objektdefinitionsmethode in der tatsächlichen Entwicklung, einschließlich des Standardmodus, der von vielen JS -Bibliotheken (Bootstrap usw.) angewendet wird.