Überblick
Alle Objekte in JavaScript haben ihre eigene Vererbungskette. Das heißt, jedes Objekt erbt ein anderes Objekt, das als "Prototyp" -Objekt bezeichnet wird. Mit Ausnahme von NULL hat es kein eigenes Prototypobjekt.
Die Bedeutung eines Prototyp -Objekts ist, dass das Objekt B, wenn Objekt A ein Prototyp von Objekt B ist, alle Eigenschaften und Methoden des Objekts A erhalten kann. GETPROTOTYPOF -Methode wird verwendet, um das Prototypobjekt des aktuellen Objekts zu erhalten.
var p = Object.getPrototypeof (OBJ);
Im obigen Code ist Objekt P das Prototypobjekt von Object OBJ.
Die Methode von Object.create wird verwendet, um ein neues Objekt zu generieren und das angegebene Objekt zu erben.
var obj = object.create (p);
Im obigen Code ist der Prototyp des neu generierten OBJ -Objekts Objekt p.
Das nicht standardmäßige __Proto__-Attribut (zwei Unterstriche vor und dahinter) können das Prototypobjekt eines bestimmten Objekts neu schreiben. Sie sollten jedoch versuchen, diese Eigenschaft so wenig wie möglich zu verwenden, verwenden jedoch Object.getPrototypeof () und Object.setPrototypeof (), um Prototyp -Objekte zu lesen und zu schreiben.
var obj = {}; var p = {}; obj .__ proto__ = p;Der obige Code legt das P -Objekt als Prototyp des OBJ -Objekts durch das __Proto__ -Attribut fest.
Hier ist ein praktisches Beispiel.
var a = {x: 1}; var b = {__Proto__: a}; bx // 1Im obigen Code legt Object B sein Prototypobjekt als Objekt über das Attribut __Proto__ fest, sodass Objekt B alle Eigenschaften und Methoden des Objekts A abrufen kann. Das B -Objekt selbst hat kein X -Attribut, aber die JavaScript -Engine findet sein Prototyp -Objekt A durch das __proto__ -Attribut und liest dann das X -Attribut von a.
Der neue Befehl erstellt ein neues Instanzobjekt über einen Konstruktor. Es bindet im Wesentlichen den Prototyp des Instanzobjekts an die Prototyp -Eigenschaft des Konstruktors und führt dann den Konstruktor auf dem Instanzobjekt aus.
var o = new foo (); // ist äquivalent zu var o = new Object (); o .__ proto__ = foo.prototype; foo.call (o);
Das eigene __Proto__ -Attribut des Prototyps Objekt kann auch auf andere Objekte verweisen, wodurch eine "Prototyp -Kette" nach Ebene bildet.
var a = {x: 1}; var b = {__Proto__: a}; var c = {__Proto__: b}; cx // 1Es ist zu beachten, dass die Suche nach einem bestimmten Attribut in der Prototyp -Kette einen Einfluss auf die Leistung hat. Je höher die Ebene des von Ihnen gesuchten Prototypobjekts, desto größer ist die Auswirkungen auf die Leistung. Wenn Sie nach einer nicht existierenden Eigenschaft suchen, durchquert dies die gesamte Prototypkette.
Diese Aktion zeigt
Unabhängig davon, wo dies definiert ist, zeigt es bei Verwendung immer auf das aktuelle Objekt, nicht auf das Prototypobjekt.
var o = {a: 2, m: function (b) {return this.a + 1; }}; var p = Object.create (o); pa = 12; pm () // 13Im obigen Code stammt die M -Methode des P -Objekts von seinem Prototypobjekt o. Zu diesem Zeitpunkt zeigt dieses Objekt in der M -Methode nicht auf o, sondern auf p.
Vererbung von Konstruktoren
In diesem Abschnitt wird vorgestellt, wie ein Konstruktor einen anderen Konstruktor erben.
Angenommen, es gibt einen Formkonstruktor.
Funktionsform () {this.x = 0; this.y = 0;} form.prototype.move = function (x, y) {this.x += x; this.y += y; console.info ('Form bewegt.');}; Der Rechteckkonstruktor erbt Form. Funktion rectangle () {form.call (this); // Rufen Sie den übergeordneten Klassenkonstruktor auf} // eine andere Möglichkeit, Funktion rechteck zu schreiben () {this.base = form; this.base ();} // Unterklasse erbt die übergeordnete Klassenmethode rechteckig.Der obige Code zeigt, dass die Vererbung des Konstruktors in zwei Teile unterteilt ist. Einer ist, dass die Unterklasse die Konstruktormethode der übergeordneten Klasse aufruft, und der andere ist, dass der Prototyp der Unterklasse auf den Prototyp der übergeordneten Klasse zeigt.
Im obigen Code erbt die Unterklasse die übergeordnete Klasse als Ganzes. Manchmal ist nur die Vererbung einer einzelnen Methode erforderlich, und die folgende Schreibmethode kann verwendet werden.
Classb.prototype.print = function () {classa.prototype.print.call (this); // ein Code}Im obigen Code ruft die Druckmethode von Unterklasse B zuerst die Druckmethode der übergeordneten Klasse A auf und bereitet dann seinen eigenen Code bereit. Dies ist gleichbedeutend mit der Erben der Druckmethode der übergeordneten Klasse A.
__Proto__ Attribut
Das __Proto__ -Attribut zeigt auf das Prototypobjekt des aktuellen Objekts, dh das Prototyp -Attribut des Konstruktors.
var obj = new Object (); obj .__ proto__ === Object.Prototype // trueobj .__ proto__ === obj.constructor.prototype // true
Der obige Code erstellt zuerst ein neues Objekt OBJ, sein __Proto__ -Attribut, das auf das Prototyp -Attribut des Konstruktors (Objekt oder Obj.Constructor) hinweist. Nach dem Vergleich der beiden kehren Sie daher wahr.
Daher gibt es drei Möglichkeiten, das Prototypobjekt des Instanzobjekts OBJ zu erhalten.
Unter den obigen drei Methoden sind die ersten beiden nicht sehr zuverlässig. Das neueste ES6 -Standard hat festgestellt, dass nur der Browser das __Proto__ -Attribut bereitstellen muss, und andere Umgebungen werden möglicherweise nicht bereitgestellt. Obj.Constructor.Prototyp kann jedoch bei manuellem Ändern des Prototypobjekts fehlschlagen.
var p = function () {}; var p = new p (); var c = function () {};Im obigen Code wird das Prototypobjekt des C -Konstruktors in P geändert, und das Ergebnis ist, dass c.constructor.Prototyp verzerrt ist. Daher sollte beim Ändern des Prototyp -Objekts das Konstruktorattribut gleichzeitig festgelegt werden.
C.Prototype = P; C.Prototype.Constructor = C;
Daher wird empfohlen, das dritte Objekt zu verwenden. Die Verwendung dieser Methode ist wie folgt.
var o = new Object (); Object.getPrototypeof (o) === Object.Prototype // true
Sie können die Methode von Object.getPrototypeof verwenden, um zu überprüfen, ob der Browser das __Proto__ -Attribut unterstützt, das nicht von alten Browsern unterstützt wird.
Object.getPrototypeof ({__Proto__: null}) === nullDer obige Code legt das __Proto__ -Attribut eines Objekts auf NULL fest und verwendet dann das Object.getPrototypeof -Methode, um den Prototyp dieses Objekts zu erhalten, um festzustellen, ob es gleich Null ist. Wenn die aktuelle Umgebung das __Proto__ -Attribut unterstützt, sollte das Vergleichsergebnis der beiden wahr sein.
Mit dem __Proto__ -Attribut ist es einfach, den Prototyp des Instanzobjekts einzurichten. Angenommen, es gibt drei Objekte: Maschine, Fahrzeug und Auto, wobei die Maschine der Prototyp von Fahrzeug und Fahrzeug ist, ist der Prototyp des Autos, der mit nur zwei Codelinien eingestellt werden kann.
Fahrzeug .__ Proto__ = Maschine; Car .__ Proto__ = Fahrzeug;
Das Folgende ist ein Beispiel. Die im Prototyp -Objekt definierten Eigenschaften werden jeweils über das Attribut __Proto__ und das Attribut constructor.prototype gelesen.
Array.prototype.p = 'abc'; var a = new array (); a .__ proto __. P // abca.constructor.prototype.p // abc
Offensichtlich sieht __Proto__ etwas prägnanter aus.
Wenn ein Instanzobjekt über einen Konstruktor erzeugt wird, weist das __Proto__ -Attribut des Instanzobjekts automatisch auf das Prototypobjekt des Konstruktors hin.
var f = function () {}; var a = {}; f.prototype = a; var o = new f ();Vererbung von Attributen
Es gibt zwei Arten von Attributen. Eines ist das native Attribut des Objekts selbst, und das andere ist das vom Prototyp geerbte ererbte Attribut.
Einheimische Eigenschaften eines Objekts
Alle Eigenschaften des Objekts selbst können mithilfe des Object.GetownPropertynames -Methode erhalten werden.
Object.getownPropertynames (Datum) // ["Parse", "Argumente", "UTC", "Anrufer", "Name", "Prototyp", "jetzt", "Länge"]
Unter den Eigenschaften des Objekts selbst sind einige aufzählbare (aufzählbare), während andere nicht aufgezählt werden. Erhalten Sie nur die Eigenschaften, die aufgezählt werden können. Verwenden Sie die Methode von Object.keys.
Object.Keys (Datum) // [] HasownProperty ()
Die HasownProperty -Methode gibt einen Booleschen Wert zurück, um festzustellen, ob eine bestimmte Eigenschaft auf dem Objekt selbst oder in der Prototypkette definiert ist.
Datum.hasownProperty ('Länge') // trueDate.hasownProperty ('tostring') // falseDie HasownProperty -Methode ist die einzige Methode in JavaScript, die die Prototyp -Kette bei der Verarbeitung von Objekteigenschaften nicht durchquert.
Vererbungseigenschaften eines Objekts
Die mit der Objekt erstellten Objekte erben die Eigenschaften aller Prototyp -Objekte.
var proto = {p1: 123}; var o = Object.create (proto); o.p1 // 123o.hasownProperty ("p1") // falseHolen Sie sich alle Attribute
Um festzustellen, ob ein Objekt über eine bestimmte Eigenschaft verfügt (ob es sich um eine eigene oder erbte oder erbte), verwenden Sie den Operator.
"Länge" im Datum // true "tostring" in Datum // true
Holen Sie sich alle aufzählbaren Eigenschaften eines Objekts (unabhängig davon, ob es eigene oder ererbt oder ererbt wird), und Sie können eine fürs In-in-Schleife verwenden.
var o1 = {p1: 123}; var o2 = Object.create (o1, {p2: {value: "abc", Enumerable: true}}); für (p in o2) {console.info (p);} // p2 // p1Um die eigenen Eigenschaften des Objekts in der für ... in Schleife zu erhalten, können Sie die HasownProperty -Methode verwenden, um zu beurteilen.
für (var name in Object) {if (Object.hasownProperty (Name)) { / * Schleifencode * /}}Um alle Eigenschaften des Objekts zu erhalten (unabhängig davon, ob es eigene oder vererbt ist und ob es aufgezählt werden kann), können Sie die folgende Funktion verwenden.
Funktion inheritedPropertynames (obj) {var props = {}; while (obj) {Object.getownPropertynames (obj) .foreach (Funktion (p) {props [p] = true;}); obj = Object.getPrototypeof (OBJ); } return Object.getownPropertynames (Requisiten);};}Die Verwendung ist wie folgt:
inheritedPropertyNames(Date)// ["caller", "constructor", "toString", "UTC", "call", "parse", "prototype", "__defineSetter__", "__lookupSetter__", "length", "arguments", "bind", "__lookupGetter__", "isPrototypeOf", "toLocaleString", "PropertyISenumerable", "Valueof", "Bewerben", "__defineGetter__", "Name", "jetzt", "HasownProperty"]
Kopie des Objekts
Wenn Sie ein Objekt kopieren möchten, müssen Sie die folgenden zwei Dinge ausführen.
Stellen Sie sicher, dass das kopierte Objekt das gleiche Prototypobjekt wie das ursprüngliche Objekt hat.
Stellen Sie sicher, dass das kopierte Objekt die gleichen Eigenschaften hat wie das ursprüngliche Objekt.
Das Folgende ist die Funktion des Kopierens des Objekts, das basierend auf den beiden oben genannten Punkten geschrieben wurde.
Funktion CopyObject (orig) {var copy = Object.create (Object.getPrototypeof (orig)); CopyownPropertiesfrom (Kopie, orig); return Copy;} Funktion CopyownPropertiesfrom (Ziel, Quelle) {Object .GetownPropertynames (Quelle) .foreach (Funktion (propey) {var desFect = Object.getownPropertyDescriptor (Quelle, Propey); Object.DefineProperty (Ziel, Propey, Desc);}); Ziel zurückgeben;}Multiple Vererbung
JavaScript liefert keine mehrfachen Vererbungsfunktionen, dh ein Objekt kann nicht gleichzeitig mehrere Objekte erben. Diese Funktion kann jedoch durch Problemumgehungen erreicht werden.
Funktion m1 (prop) {this.hello = prop;} Funktion m2 (prop) {this.world = prop;} Funktion s (p1, p2) {this.base1 = m1; this.base1 (p1); this.base2 = m2; this.base2 (p2);} S.Prototype = new M1 (); var s = new s (111, 222); S.Hello // 111S.World // 222Im obigen Code erbt die Unterklasse S sowohl übergeordnete Klassen M1 als auch M2. Natürlich hat S aus Sicht der Erbungskette nur eine übergeordnete Klasse M1, aber da die Konstruktoren von M1 und M2 gleichzeitig ausgeführt werden, erbt sie gleichzeitig die Methoden dieser beiden Klassen.