1.Prototyp -Objekt
1.1 Nachteile von Konstruktoren
JavaScript generiert neue Objekte über Konstruktoren, sodass Konstruktoren als Vorlagen für Objekte betrachtet werden können. Die Eigenschaften und Methoden des Instanzobjekts können im Konstruktor definiert werden.
Funktion cat (Name, Farbe) {this.name = name; this.color = color;} var cat1 = new Cat ('Big Hair', 'White'); Cat1.Name // 'Big Hair'cat1.color //' White ''Die Katzenfunktion im obigen Code ist ein Konstruktor. Das Namensattribut und das Farbattribut werden intern definiert. Alle Instanzobjekte generieren diese beiden Attribute. Dies ist jedoch eine Verschwendung von Systemressourcen, da Eigenschaften nicht zwischen Objektinstanzen desselben Konstruktors geteilt werden können.
Funktion cat (Name, Farbe) {this.name = name; this.color = color; this.meow = function () {console.log ('Mew, Mew, Mew ...'); };} var cat1 = new Cat ('Big Hair', 'White'); var cat2 = new Cat ('ei mao', 'schwarz'); Cat1.meow === Cat2.meow // falseIm obigen Code sind CAT1 und CAT2 Instanzen desselben Konstruktors. Ihre Meow -Methoden sind jedoch unterschiedlich, dh jedes Mal, wenn eine neue Instanz erstellt wird, wird eine neue MEOW -Methode erstellt. Dies ist weder notwendig noch Verschwendung von Systemressourcen, da alle Meow -Methoden das gleiche Verhalten sind und vollständig geteilt werden sollten.
1.2 Die Rolle des Prototyp -Attributs
In JavaScript -Sprache verfügt jedes Objekt über ein entsprechendes Prototypobjekt, das als Prototypobjekt bezeichnet wird. Alle im Prototypobjekt definierten Eigenschaften und Methoden können vom abgeleiteten Objekt vererbt werden. Dies ist das grundlegende Design des JavaScript -Vererbungsmechanismus.
Zusätzlich zu diesem Ansatz bietet JavaScript auch eine weitere Möglichkeit, Instanzobjekte zu definieren. Wir wissen, dass ein Konstruktor eine Funktion, ein Objekt ist und auch seine eigenen Eigenschaften und Methoden hat. Ein Prototyp -Attribut zeigt auf ein anderes Objekt, das allgemein als Prototypobjekt bezeichnet wird. Dieses Objekt ist etwas ganz Besonderes. Solange die darauf definierten Eigenschaften und Methoden von allen Instanzobjekten geteilt werden können. Das heißt, wenn der Konstruktor ein Instanzobjekt generiert, wird dem Instanzobjekt automatisch ein Prototypattribut zugeordnet.
Funktion Animal (Name) {this.name = name;} Animal.Prototype.color = "White"; var cat1 = new Animal ('Big Hair'); var cat2 = new Animal ('erimao'); Cat1.color // 'White'cat2.color //' White ''Der obige Code fügt dem Prototypobjekt des Konstruktortiers ein Farbattribut hinzu. Infolgedessen tragen sowohl Instanzobjekte CAT1 als auch Cat2 diese Eigenschaft.
Insbesondere, solange das Prototypobjekt geändert wird, werden die Änderungen sofort im Instanzobjekt reflektiert.
Animal.Prototype.color = "Yellow"; cat1.color // 'gelb'cat2.color //' gelb '
Der obige Code ändert den Wert des Farbattributs des Prototyp -Objekts in Gelb, und der Wert des Farbattributs der beiden Instanzobjekte ändert sich sofort. Dies liegt daran, dass das Instanzobjekt tatsächlich kein Farbattribut hat und alle das Farbattribut des Prototyps -Objekts lesen. Das heißt, wenn das Instanzobjekt selbst keine bestimmte Eigenschaft oder Methode hat, geht es zum Prototyp -Objekt des Konstruktors, um die Eigenschaft oder Methode zu finden. Dies ist das Besondere an Prototypobjekten.
Wenn das Instanzobjekt selbst eine bestimmte Eigenschaft oder Methode hat, wird im Prototypobjekt nicht mehr diese Eigenschaft oder Methode angezeigt.
cat1.color = 'schwarz'; cat2.color // 'gelb'animal.prototype.color // "gelb";
Der obige Code ändert die Farbeigenschaft des Instanzobjekts Cat1 in Schwarz, sodass er die Farbeigenschaft nicht mehr aus dem Prototyp -Objekt lesen muss und der Wert des letzteren immer noch gelb ist.
Kurz gesagt, die Funktion des Prototyp -Objekts besteht darin, die Eigenschaften und Methoden zu definieren, die von allen Instanzobjekten geteilt werden, und wird daher auch als Prototyp des Instanzobjekts bezeichnet, und das Instanzobjekt kann als aus dem Prototyp -Objekt abgeleitet angesehen werden.
Animal.Prototype.walk = function () {console.log (this.name + 'geht.');};Der obige Code definiert eine Walk -Methode im Animal.Protype -Objekt, das alle Tierinstanzobjekte aufgerufen wird.
1.3 Prototyp -Kette
Da alle Objekte in JavaScript Konstruktoren haben und alle Konstruktoren Prototypattribute haben (tatsächlich haben alle Funktionen Prototypattribute), haben alle Objekte ihre eigenen Prototyp -Prototyp -Objekte.
Daher können die Eigenschaften und Methoden eines Objekts auf sich selbst oder an seinem Prototypobjekt definiert werden (wie die Walk -Methode im obigen Code). Da der Prototyp selbst ein Objekt ist und einen eigenen Prototyp hat, wird eine Prototypkette gebildet. Zum Beispiel ist Objekt A der Prototyp von Objekt B, Objekt B ist der Prototyp von Objekt C und so weiter. Da die Wurzel der Quelle nachverfolgt werden, werden die Objekte an der Quelle aus dem Objektkonstruktor (mit dem Befehl neu Object ()) generiert. Gibt es also einen Prototyp für Object.Prototyp? Die Antwort kann Ja oder Nein sein, da der Prototyp des Objekts ein Null ohne Eigenschaften und Methoden ist.
Object.getPrototypeof (Object.Prototype) // null
Der obige Code zeigt an, dass der Prototyp des Objekts.Prototyp -Objekts null ist. Da Null keine Eigenschaften hat, endet die Prototypkette hier.
Die Funktion der "Prototyp -Kette" ist, dass die JavaScript -Engine beim Lesen eines bestimmten Attributs eines Objekts zuerst nach den Attributen des Objekts selbst sucht. Wenn es nicht gefunden werden kann, wird es nach seinem Prototyp suchen. Wenn es immer noch nicht gefunden werden kann, wird nach dem Prototyp des Prototyps suchen. Und so weiter, wenn das Objekt.Prototyp auf der oberen Ebene noch nicht gefunden wird, kehrt es undefiniert zurück.
Wenn beispielsweise das Prototyp -Attribut einer Funktion auf ein Array zeigt, bedeutet dies, dass die Funktion als Array -Konstruktor verwendet werden kann, da die von ihr generierten Instanzobjekte die Array -Methode über das Prototyp -Attribut aufrufen können.
Funktion myarray () {} myarray.prototype = new array (); myarray.prototype.constructor = myarray; var mine = new myarray (); mine.push (1, 2, 3); MineDie Mine im obigen Code ist ein Instanzobjekt von MyArray. Da die Prototyp -Eigenschaft von MyArray auf ein Array zeigt, kann Mine Array -Methoden aufrufen (diese Methoden werden tatsächlich auf dem Prototypobjekt des Arrays definiert). Wie für die letzte Linie der Instanze der Expression wissen wir, dass der Instanz des Operators verwendet wird, um zu vergleichen, ob ein Objekt eine Instanz eines Konstruktors ist, und die letzte Zeile zeigt an, dass Mine eine Instanz des Arrays ist.
Mine Instance von Array // entspricht (array === myarray.prototype.constructor) || (array === array.prototype.constructor) || (Array === Object.Prototype.Constructor)
Der obige Code veranschaulicht die Essenz des Instanzoperators, der mit den Konstruktorattributen aller Prototypobjekte des Instanzobjekts verglichen wird (für die Einführung dieses Attributs finden Sie im nächsten Abschnitt). Solange es einen gibt, wird es wahr zurückkehren, sonst gibt es false zurück.
1.4 Konstruktorattribut
Das Prototyp -Objekt verfügt über ein Konstruktorattribut, das auf die Konstruktorfunktion hinweist, in der sich das Prototyp -Objekt standardmäßig befindet.
Funktion p () {} p.Prototype.Constructor === P // TrueDa das Konstruktorattribut auf dem Prototypobjekt definiert ist, bedeutet es, dass es von allen Instanzobjekten vererbt werden kann.
Funktion p () {} var p = new P (); P.Constructor // Funktion p () {} P.Constructor === P.Prototype.Constructor // Truep.hasownProperty ('Constructor') // FalseDer obige Code zeigt an, dass P ein Instanzobjekt von Konstruktor P ist, P selbst kein Konstruktorattribut hat, das tatsächlich das Attribut prototyps.constructor in der Prototypkette liest.
Die Funktion des Konstruktorattributs besteht darin, zu unterscheiden, welcher Konstruktor das Prototypobjekt definiert ist.
Funktion f () {}; var f = new f ();Der obige Code bedeutet, dass die Verwendung der Konstruktoreigenschaft festgestellt wird, dass die Konstruktorfunktion der Variablen f f ist, nicht regexp.
2.Object.getPrototypeof Methode
Die Methode von Object.getPrototypen gibt den Prototyp eines Objekts zurück.
// Der Prototyp des leeren Objekts ist Object.PrototypeObject.getPrototypeof ({}) === Object.Prototyp // true // Der Prototyp der Funktion ist Funktion. Prototyp von f ist f.Prototypevar f = new f (); Object.getPrototypeof (f) === F.Prototype // true3.Object.create -Methode
Die Methode von Object.create wird verwendet, um ein neues Objekt zu generieren und den neuen Befehl zu ersetzen. Es akzeptiert ein Objekt als Argument und gibt ein neues Objekt zurück, das die Eigenschaften des ersteren vollständig erbt, dh der erstere wird zum Prototyp des letzteren.
var o1 = {p: 1}; var o2 = Object.create (o1); o2.p // 1Im obigen Code generiert das Object.create -Methode O2 basierend auf O1. Zu diesem Zeitpunkt wird O1 zum Prototyp von O2, dh O2 erbt alle Eigenschaften von O1.
Die Methode von Object.create entspricht im Grunde genommen dem folgenden Code. Wenn der alte Browser die Methode von Object.create nicht unterstützt, können Sie den folgenden Code selbst verwenden, um es selbst bereitzustellen.
if (typeof object.create! Neue f () zurückgeben; };}
Der obige Code zeigt, dass die Methode von Object.create im Wesentlichen einen neuen Konstruktor F erstellt und dann das Prototyp -Attribut von F als Prototyp auf Objekt O verweist und schließlich eine Instanz von F zurückgibt, damit die Instanz die Attribute von O erben kann.
Die auf den folgenden drei Arten erzeugten neuen Objekte sind gleichwertig.
var O1 = Object.create ({}); var o2 = Object.create (Object.Prototyp); var o3 = new Object ();Wenn Sie ein Objekt generieren möchten, das keine Eigenschaften (z. B. ToString- und ValueOF -Methoden) erbt, können Sie das Objekt festlegen.
var o = Object.create (null);
Der obige Code zeigt an, dass der Prototyp von Objekt O null nicht einige Eigenschaften auf dem Objekt definiert hat.
Bei der Verwendung der Methode von Object.create muss ein Objektprototyp bereitgestellt werden, andernfalls wird ein Fehler gemeldet.
Object.create () // Typeerror: Der Objektprototyp darf möglicherweise nur ein Objekt oder Null sein
Das vom Objekt generierte neue Objekt. Create -Methode erbt dynamisch den Prototyp. Das Hinzufügen oder Ändern einer Methode im Prototyp reflektiert sofort das neue Objekt.
var o1 = {p: 1}; var o2 = Object.create (O1); O1.p = 2; o2.p // 2Der obige Code zeigt an, dass das Ändern des Objektprototyps das neu generierte Objekt beeinflusst.
Zusätzlich zum Objektprototyp kann die Methode von Object.create auch einen zweiten Parameter akzeptieren, der das Attribute -Objekt darstellt, das die Attribute beschreibt, die das gleiche Format wie das Objekt ist. Die beschriebenen Objekteigenschaften werden dem neuen Objekt hinzugefügt.
var o = Object.create (Object.Prototype, {p1: {value: 123, Enumerable: true}, p2: {value: "abc", Enumerable: true}}); O.P1 // 123o.p2 // "abc"Da die Methode von Object.create keinen Konstruktor verwendet, kann der Instanzoperator nicht verwendet werden, um zu bestimmen, welche Konstruktorinstanz das Objekt ist. Zu diesem Zeitpunkt können Sie die folgende ISPrototype -Methode verwenden, um zu interpretieren, welches Objekt der Prototyp ist.
4.ISRTOTOTYPEOF -Methode
Die isprototype -Methode wird verwendet, um festzustellen, ob ein Objekt ein Prototyp eines anderen Objekts ist.
var O1 = {}; var o2 = Object.create (O1); var o3 = Object.create (o2); o2.isprototypeof (O3) // trueo1.isprototypeof (o3) // trueDer obige Code zeigt, dass iSprotypeof true zurückgibt, solange sich ein Objekt in der Prototypkette befindet.
5. Ein einfaches Beispiel
var classDemo = function () {// statische private variable varable var private_static_var = 'aaaa'; // statische private Methode var private_static_func = Funktion (Schlüssel) {Rückgabeschlüssel + private_static_var; } // private Methode ist der Schlüssel, diese var private_func = function (self, key) {return private_static_func (Schlüssel + self.id); } var _class = function (id) {// constructor this.id = id; // public variable} // public method_class.prototype.public_func = Funktion (Schlüssel) {return private_func (this, key); } return _class;} (); var a = new classDemo ('Hello World'); alert (a.public_func ('World Hallo'));Es gibt keine einfache Möglichkeit, private Variablen und öffentliche statische Variablen/Methoden zu implementieren, aber die Kapselung reicht aus, um in diesem Ausmaß durchgeführt zu werden.