Beim Erstellen von Objekten über Objektkonstruktoren oder Objektliterale wird beim Erstellen vieler Objekte mit derselben Schnittstelle eine große Menge doppelter Code generiert. Der Einfachheit halber wurde das Fabrikmodell eingeführt.
Fabrikmodell
Funktion CreatePerson (Name, Alter, Job) {var obj = new Object (); obj.name = name; obj.age = Alter; obj.job = Job; obj.sayhello () {alert (this.name); }; return obj;} var p1 = createPerson ("xxyh", 19, "Programmierer"); var p2 = createPerson ("Zhangsan", 18, "Student");Diese Art, Objekte zu erstellen, vereinfacht den Code erheblich, aber es gibt auch ein Mangel, dh die Art des Objekts kann nicht bestimmt werden. Um dieses Problem zu lösen, erscheint das folgende Muster.
Konstruktormodus
Erstellen Sie einen benutzerdefinierten Konstruktor, um Eigenschaften und Methoden benutzerdefinierter Objekttypen zu definieren.
Funktionsperson (Name, Alter, Job) {this.name = name; this.age = Alter; this.job = Job; this.sayname = function () {alert (this.name); };} var p1 = new Person ("xxyh", 19, "Programmierer"); var p2 = neue Person ("Jack", 18, "Student");Im obigen Beispiel ersetzt Person () CreatePerson (). Darüber hinaus gibt es verschiedene Unterschiede:
• Objekte ohne Anzeige erstellen;
• Weisen Sie diesem Objekt direkt Attribute und Methoden zu
• Keine Rückgabeerklärung
Um ein Personenobjekt zu erstellen, müssen Sie den neuen Bediener verwenden. Es ist in 4 Schritte unterteilt:
• Erstellen Sie ein neues Objekt
• Weisen Sie dem Konstruktor einem neuen Objekt den Umfang des Konstruktors zu
• Führen Sie den Code im Konstruktor aus
• Neues Objekt zurückgeben
P1 bzw. P2 speichern eine Instanz der Person.
alert (p1.constructor == Person); // Truealert (p2.Constructor == Person); // WAHR
Es ist am besten, Instanz bei der Erkennung von Typen zu verwenden:
ALERT (P1 -Instanz des Objekts); // Truealert (p1 -Instanz der Person); // Truealert (P2 -Instanzobjekt); // Truealert (p2 -Instanz der Person); // Truealert (p2 -Instanz der Person); // WAHR
P1 und P2 sind Objektfälle, da alle Objekte von Objekt geerbt werden.
2.1 Konstruktoren als Funktionen behandeln
// Verwenden Sie var Person = New Person ("xxyh", 19, "Programmierer"); Person.SayName (); // "xxyh" // als normale Funktionsperson ("Zhangsan", 18, "Student"); // zu WindowWindow.sayName () hinzufügen; // "Zhangsan" // nenn var obj im Bereich eines anderen Objekts obj = neues Objekt (); Person.call (obj, "Jack", 29, "Manager"); obj.sayname (); // "Jack", OBJ hat alle Eigenschaften und Methoden2.2 Konstruktorproblem
Das Problem bei der Verwendung von Konstruktoren besteht darin, dass jede Methode in jeder Instanz nachgebildet werden muss. P1 und P2 haben beide eine SayName () -Methode, aber sie sind keine Funktionen der Funktion. In JavaScript ist eine Funktion ein Objekt. Jedes Mal, wenn eine Funktion definiert wird, wird ein Objekt instanziiert.
Der Konstruktor kann auch so definiert werden:
Funktionsperson (Name, Alter, Job) {this.name = name; this.age = Alter; this.job = Job; this.sayname = new Function ("alert (this.name)");}Daher sind die gleichnamigen Funktionen in verschiedenen Fällen nicht gleich:
alert (p1.sayname == p2.SayName); // FALSCH
Das Erstellen von zwei Funktionen mit derselben Funktion ist jedoch überflüssig, und es ist nicht erforderlich, die Funktion vor der Ausführung des Codes an ein bestimmtes Objekt zu binden.
Funktionsperson (Name, Alter, Job) {this.name = name; this.age = Alter; this.job = Job; this.sayname = sayName;} Funktion Sayname () {alert (this.name);} var p1 = new Person ("xxyh", 19, "Programmierer"); var p2 = new Person ("Jack", 18, "Student");Das obige bewegt die Definition von SayName () außerhalb des Konstruktors und legt dann das Attribut SayName als globale SayName -Funktion innerhalb des Konstruktors fest. Auf diese Weise enthält SayName einen Zeiger auf die Funktion, und P1 und P2 teilen die gleiche SayName () -Funktion, die im globalen Bereich definiert ist.
Dies gibt jedoch ein neues Problem: Funktionen, die im globalen Bereich definiert sind, können nur von einem bestimmten Objekt aufgerufen werden. Und wenn das Objekt viele Methoden definiert, verliert der Referenztyp seine Kapselung.
Prototyp -Kettenmodus
Jede Funktion verfügt über eine Prototyp -Eigenschaft, die ein Zeiger ist, der auf ein Objekt zeigt. Der Zweck dieses Objekts besteht darin , Eigenschaften und Methoden einzubeziehen, die von allen Instanzen eines bestimmten Typs geteilt werden können . Prototyp ist das Prototypobjekt dieser Objektinstanz, das durch Aufrufen des Konstruktors erstellt wurde. Der Vorteil der Verwendung eines Prototyp -Objekts besteht darin, dass alle Objektinstanzen die Eigenschaften und Methoden teilen können, die es enthält. Dies bedeutet, dass diese Informationen dem Prototyp -Objekt hinzugefügt werden, anstatt die Informationen der Objektinstanz im Konstruktor zu definieren.
Funktion person () {} person.Prototype.name = "xxyh"; Person.Prototype.age = 19; Person.Prototype.job = "Programmer"; Person.Prototyp.SayName = function () {alert (this.name);}; var person1 = new Person (); Person1.SayName (); // "xxyh" var person2 = new Person (); Person2.SayName (); // "xxyh" alert (person1.sayname == Person2.SayName); // WAHR3.1 Prototypobjekte verstehen
Erstellen Sie einfach eine neue Funktion, eine Prototyp -Eigenschaft wird für die Funktion erstellt, die auf das Prototyp -Objekt der Funktion hinweist. Standardmäßig erhalten alle Prototypobjekte automatisch eine Konstruktoreigenschaft. Diese Eigenschaft enthält einen Zeiger auf die Funktion, in der sich die Prototyp -Eigenschaft befindet. Person.Prototype.Constructor zeigt auf Person.
Wenn der Konstruktor aufgerufen wird, um eine Instanz zu erstellen, enthält das Innere der Instanz einen Zeiger (interne Eigenschaft) auf das Prototyp -Objekt des Konstruktors, genannt [[Prototyp]]. Zugriff über _Proto in Firefox, Safari und Chrome. Diese Verbindung besteht zwischen der Instanz und dem Prototypobjekt des Konstruktors, nicht zwischen der Instanz und dem Konstruktor.
Die folgende Abbildung zeigt die Beziehung zwischen jedem Objekt:
Person.Prototyp verweist auf das Prototyp -Objekt und person.Prototype.Constructor zeigt auf Person. Zusätzlich zum Konstruktorattribut gibt es im Prototyp andere hinzugefügte Attribute. Personen -Instanzen enthalten alle eine interne Eigenschaft, die nur auf Person.Prototyp verweist, und sie haben keine direkte Beziehung zum Konstruktor.
Obwohl [[[[[Prototyp]]] nicht zugegriffen werden kann, kann die Methode isprototypeof () verwendet werden, um festzustellen, ob eine solche Beziehung zwischen Objekten besteht.
alert (person.Prototype.riprototypeof (Person1)); // Truealert (person.Prototype.riprototypeof (Person2)); // WAHR
Beim Lesen der Eigenschaften eines Objekts wird eine Suche mit dem Ziel des Attributs mit dem gegebenen Namen durchgeführt. Die Suche beginnt mit der Objektinstanz selbst. Die Suche beginnt von der Objektinstanz selbst. Wenn in der Instanz ein Attribut mit dem angegebenen Namen gefunden wird, wird der Wert des Attributs zurückgegeben. Wenn es nicht gefunden wird, suchen Sie weiter nach dem vom Zeiger angezeigten Prototyp -Objekt und suchen Sie nach dem Attribut mit dem angegebenen Namen im Prototyp -Objekt. Wenn diese Eigenschaft im Prototyp -Objekt gefunden wird, wird der Wert der Eigenschaft zurückgegeben.
Die im Prototyp gespeicherten Werte können über die Objektinstanz zugegriffen werden. Die im Prototyp gespeicherten Werte können jedoch nicht über die Objektinstanz umgestellt werden . Wenn Sie der Instanz mit demselben Namen wie ein Attribut im Instanzprototyp ein Attribut hinzufügen, blockiert das Attribut das Attribut im Prototyp.
Funktion person () {} Person.Prototype.name = "xxyh"; Person.Prototype.age = "20"; Person.Prototype.job = "Programmierer"; Person.Prototype.SayName = function () {alert (this.name); "oooo"; alarm (Person1.Name); // "oooo" alarm (Person2.Name); // "xxyh"Im obigen Beispiel blockiert das Namensattribut persönlich das Namensattribut im Prototyp.
Wenn eine Objektinstanz ein Attribut hinzugefügt wird, blockiert dieses Attribut die gleichnamigen Attribute, die im Prototyp -Objekt gespeichert sind. Dies bedeutet, dass die Existenz dieser Eigenschaft den Zugang zu dieser Eigenschaft im Prototyp verhindern wird. Verwenden Sie Löschen, um Instanzeigenschaften zu löschen.
Funktion person () {} Person.Prototype.name = "xxyh"; Person.Prototype.age = "20"; Person.Prototype.job = "Programmierer"; Person.Prototype.SayName = function () {alert (this.name); "oooo"; alarm (Person1.Name); // "oooo" alarm (Person2.Name); // "xxyh" Person löschen1.Name; alert (Person1.Name); // "xxyh"HasownProperty () kann feststellen, ob in einem Fall oder in einem Prototyp eine Eigenschaft vorhanden ist.
Funktion person () {} Person.Prototype.name = "xxyh"; Person.Prototype.age = "20"; Person.Prototype.job = "Programmer"; Person.Prototype.sayname = function () {alert (this.name);}; var person1 = new Person (); Person (); alert (Person1.hasownProperty ("Name")); // falschperson1.name = "oooo"; alert (Person1.hasownProperty ("Name")); // WAHRDie folgende Abbildung zeigt die Beziehung zwischen Implementierung und Prototyp in verschiedenen Situationen:
3.2 Prototyp und Operator
So verwenden Sie den In-Operator: Verwenden Sie ihn alleine in einer für die In-In-Schleife. Wenn der Operator alleine verwendet wird, gibt er bei der Zugriffe auf eine bestimmte Eigenschaft über das Objekt true zurück , unabhängig davon, ob er in der Instanz oder im Prototyp vorliegt.
Funktion person () {} Person.Prototype.name = "xxyh"; Person.Prototype.age = "20"; Person.Prototype.job = "Programmer"; Person.Prototype.SayName = function () {alert (this.name);}; var person1 = new Person (); // trueperson1.name = "oooo"; alert ("name" für Person1); // WAHRIn Kombination mit der vorherigen Funktion von HasownProperty () kann festgestellt werden, dass eine Eigenschaft eine Eigenschaft im Prototyp oder eine Eigenschaft in der Instanz ist. Wenn der In -Operator true zurückgibt und HasownProperty falsch zurückgibt, ist die Eigenschaft eine Eigenschaft im Prototyp.
Funktion hasPrototypeproperty (Objekt, Name) {return! Object.hasownProperty (Name) && (Name in Object);}Schauen wir uns als nächstes die Verwendung von HasPrototypeproperty () an:
Funktion person () {} person.Prototype.name = "xxyh"; Person.Prototype.age = "20"; Person.Prototype.job = "Programmierer"; Person.Prototype.SayName = function () {alert (this.name); // trueperson.name = "oooo"; alert (hasPrototypeproperty (Person, "Name")); // FALSCHBei der Verwendung der For-In-Schleife alle aufzählbaren Eigenschaften, auf die über das Objekt zugegriffen werden kann, einschließlich Eigenschaften in der Instanz und Eigenschaften des Prototyps. Instanzattribute, die die nicht untermauerbaren Daten im Prototyp blockieren (d. H. Attribute, die von [[[[[[[[[[[[[[[[[[aufzähl "]] gekennzeichnet sind) werden ebenfalls in for-in zurückgegeben, da gemäß den Vorschriften alle von Entwicklern definierten Attribute aufzählbar sind.
Um alle aufzählbaren Instanzeigenschaften für ein Objekt zu erhalten, können Sie die Methode von Object.keys () verwenden.
Funktion person () {} Person.Prototype.name = "xxyh"; Person.Prototype.age = "20"; Person.Prototype.job = "Programmierer"; Person.Prototype.sayname = function () {alert (this.name); // Name, Alter, Job, sayNamevar p1 = new Person (); // Name, AlterWenn Sie alle Instanzeigenschaften erhalten müssen, können Sie die Methode von Object.getownPropertynames () verwenden
var keys = Object.getownPropertynames (Person.Prototype); alert (Schlüssel); // "Konstruktor, Name, Alter, Job, Sayname"
3.3 Einfachere Prototypsyntax
Um die Eingabe zu optimieren, überschreiben Sie das integrierte Prototyp -Objekt mit einem Objektliteral, das alle Eigenschaften und Methoden enthält.
Funktion person () {} person.Prototype = {name: "xxyh", Alter: 18, Job: "Programmierer", sayName: function () {alert (this.name); }};Die obige Person legt Person.Prototyp so fest, dass es einem neuen Objekt entspricht, das in Objektliteralform erstellt wurde. Das Ergebnis ist das gleiche, aber das Konstruktorattribut zeigt nicht mehr auf die Person.
Das korrekte Ergebnis kann durch Instanz zurückgegeben werden, aber der Konstruktor kann den Typ des Objekts nicht bestimmen:
var boy = new Person (); alert (Boy Instance of Object); // Truealert (Boy Instance von Person); // Truealert (Boy.Constructor == Person); // falsealert (Boy.Constructor == Objekt); // WAHR
Der Konstruktorwert kann auf folgende Weise festgelegt werden:
Funktion person () {} Person.Prototype = {Konstruktor: Person, Name: "xxyh", Alter: 18, Job: "Programmierer", sayname: function () {alert (this.name); }};3.4 Dynamik von Prototypketten
Da es sich bei dem Prozess des Finden von Werten in einem Prototyp um eine Suche handelt, werden alle Änderungen am Prototypobjekt auf der Instanz widerspiegelt. Wenn das gesamte Prototypobjekt jedoch umschreibt, ist das Ergebnis unterschiedlich. Beim Aufrufen des Konstruktors wird ein Zeiger auf den ursprünglichen Prototyp zur Instanz hinzugefügt, und das Ändern des Prototyps an ein anderes Objekt ist gleichbedeutend mit dem Abbau der Verbindung zwischen dem Konstruktor und dem ursprünglichen Prototyp. Der Zeiger in der Instanz zeigt nur auf den Prototyp, nicht auf den Konstruktor.
Funktion person () {} var boy = new Person (); Person.Prototype = {Konstruktor: Person, Name: "xxyh", Alter: 29, Job: "Programmierer", SayName: function () {alert (this.name); }}; boy.sayname (); // FehlerDer spezifische Prozess ist wie folgt:
Wie aus oben ersichtlich ist, schreibt das Umschreiben von Prototyp -Objekten die Verbindung zwischen vorhandenen Prototypen und bisher vorhandenen Objektinstanzen ab. Sie beziehen sich auf den ursprünglichen Prototyp.
3.5 Prototyp des nativen Objekts
Alle nativen Referenztypen definieren Methoden im Prototyp des Konstruktors. Durch den Prototyp des nativen Objekts kann nicht nur die Standardmethode erhalten werden, sondern auch eine neue Methode definiert werden.
String.Prototype.Startswith = Funktion (text) {return this.indexof (text) == 0;}; var msg = "guten Morgen"; alert (msg.startswith ("good"); // WAHR3.6 Probleme mit Prototypobjekten
Es gibt zwei Probleme mit dem Prototypmuster:
• Alles der gleiche Attributwert standardmäßig.
• Alle Attribute im Prototyp werden von der Instanz gemeinsam genutzt
Lassen Sie uns unten ein Beispiel sehen:
Funktion person () {} Person.Prototype = {Konstruktor: Person, Name: "xxyh", Alter: 18, Job: "Programmierer", Freunde: ["Zhang san", "li si"], sayname: function () {alert (this.name); }}; var p1 = new Person (); var p2 = new Person (); p1.friends.push ("wang wu"); alert (p1.friends); // Zhang San, Li Si, Wang Wu Alert (p2.freunde); // Zhang San, Li Si, Wang Wu Alert (p1.friends == p2.friends); // WAHREin Artikel wurde oben über p1.freunde hinzugefügt. Da das Friends -Array persönlich existiert. Instanzen haben jedoch im Allgemeinen alle ihre eigenen Attribute.
Verwenden Sie den Konstruktormodus und den Prototypenmodus in Kombination
Der Konstruktormodus wird verwendet, um Instanzeigenschaften zu definieren, und der Prototypmodus wird verwendet, um Methoden und gemeinsame Eigenschaften zu definieren. Auf diese Weise hat jede Instanz eine eigene Kopie der Instanzattribute, aber gleichzeitig einen Verweis auf die Methode.
Funktionsperson (Name, Alter, Job) {this.name = name; this.age = Alter; this.job = Job; this.friends = ["Zhang san", "li si"];} Person.Prototype = {Konstruktor: Person, SayName: function () {alert (this.name); }} var p1 = new Person ("xiao xiao yihan", 18, "Programmierer"); var p2 = new Person ("kuiba", 10, "Monster Hunt"); // Zhang San, Li Si, Wang Wus Alarm (p2.freunde); // Zhang san, li si alarm (p1.friends == p2.friends); // falsalSealert (p1.sayname == p2.SayName); // WAHRIm obigen Beispiel werden die Instanzeigenschaften im Konstruktor definiert, während der gemeinsam genutzte Eigenschaftskonstruktor und die Methode SayName () im Prototyp definiert sind. Die Änderung von P1.freunden wirkt sich nicht auf die Ergebnisse von P2.freunden aus.
Dynamischer Prototypmodus
Das dynamische Prototyp -Muster verkaps alle Informationen im Konstruktor und durch Initialisierung des Prototyps im Konstruktor behält es den Vorteil, sowohl den Konstruktor als auch den Prototyp zu verwenden. Das heißt, es ist möglich zu bestimmen, ob der Prototyp initialisiert werden muss, indem überprüft werden muss, ob eine vorhandene Methode wirksam ist.
Funktionsperson (Name, Alter, Job) {// Eigenschaft this.name = name; this.age = Alter; this.job = Job; // Methode if (typeof this.sayname! }}}Dies wird dem Prototyp nur hinzugefügt, wenn die Methode sayName () nicht vorhanden ist, und wird nur ausgeführt, wenn der Konstruktor zum ersten Mal aufgerufen wird.
Parasitäres Konstruktormuster
Die Idee dieses Musters besteht darin, eine Funktion zu erstellen, deren Funktion darin besteht, den Code zu verkörpern, der das Objekt erstellt und dann das neu erstellte Objekt zurücksetzt.
Funktionsperson (Name, Alter) {var obj = new Object (); obj.name = name; obj.age = Alter; obj.sayname = function () {alert (this.name); } return obj;} var boy = new Person ("xxyh", 19, "Programmierer"); boy.sayname ();Es sollte angemerkt werden: Zunächst hat das zurückgegebene Objekt keine Beziehung zum Konstruktor oder zu den Prototypattributen des Konstruktors; Das vom Konstruktor zurückgegebene Objekt unterscheidet sich nicht von dem außerhalb des Konstruktors erstellten Objekts. Der Instanz des Operators kann nicht auf den Objekttyp ermittelt werden.
Stabiles Konstruktormuster
Ein sicheres Objekt bezieht sich auf ein Objekt, das keine öffentlichen Attribute hat, und seine Methoden beziehen sich nicht darauf. Stabile Konstruktoren folgen einem ähnlichen Muster wie parasitären Konstruktoren, aber es gibt zwei Unterschiede:
• Die Instanzmethode des neu erstellten Objekts bezieht sich nicht darauf.
• Der Konstruktor wird nicht mit dem neuen Bediener aufgerufen
Schreiben Sie den Personkonstruktor wie folgt neu:
Funktionsperson (Name, Alter, Job) {var obj = new Object (); obj.sayname = function () {alert (name); }; Rückgabe obj;} Funktionsperson (Name, Alter, Job) {var obj = new Object (); obj.sayname = function () {alert (name); }; Rückgabe obj;}In dem obigen Artikel handelt es sich kurz um die Erstellung von JavaScript -Objekten handelt es sich um den Inhalt, den ich mit Ihnen teile. Ich hoffe, es kann Ihnen eine Referenz geben und ich hoffe, Sie können Wulin.com mehr unterstützen.