In den meisten Programmiersprachen gibt es Klassen und Objekte, und eine Klasse kann andere Klassen erben.
In JavaScript basiert die Vererbung auf Prototypen, was bedeutet, dass es in JavaScript keine Klassen gibt, und stattdessen erbt ein Objekt ein anderes Objekt. :)
1. Vererbung, der Proto
In JavaScript, wenn ein Objekt Kaninchen ein anderes Objekttier erbt, bedeutet dies, dass es im Kaninchenobjekt eine besondere Eigenschaft gibt: Kaninchen .__ Proto__ = Tier;
Wenn der Dolmetscher die Eigenschaft auf einem Kaninchen nicht finden kann, folgt es der __Proto__ -Kette, wenn der Interpreter nicht auf dem Tierobjekt gesucht wird
Das __Proto__ -Attribut in Kastanien ist nur in Chrome und Firefox zugänglich. Bitte sehen Sie eine Kastanie:
var Animal = {ess: true} var rabbit = {springt: true} Rabbit .__ proto__ = Animal // InHeritert (Rabbit.eats) // TrueDas EISS -Attribut wird von einem Tierobjekt aus zugegriffen.
Wenn das Attribut im Kaninchenobjekt gefunden wurde, wird das Proto -Attribut nicht überprüft.
Lassen Sie uns noch eine Kastanie haben. Wenn in der Unterklasse auch ein ESS -Attribut vorhanden ist, wird auf die übergeordnete Klasse nicht zugegriffen.
var Animal = {ess: true} var feduprabbit = {iss: false} feduprabbit .__ proto__ = Animal Alert (Feduprabbit.eats) // FalseSie können auch eine Funktion im Tier hinzufügen und auf Kaninchen zugreifen.
var Animal = {eat: function () {alert ("Ich bin voll") this.full = true}} var Rabbit = {sprung: function () { / * etwas * /} Rabbit .__ proto__ = timal(1) Rabbit.eat ():
Die Funktion Rabbit.eat () wird in den folgenden zwei Schritten ausgeführt:
Erstens sucht der Dolmetscher nach Kaninchen. Es gibt keine Essensfunktion im Kaninchen, also schaut es entlang von Kaninchen auf .__ Proto__ und fand sie im Tier.
Die Funktion läuft mit diesem = Kaninchen. Dieser Wert hat nichts mit dem __Proto__ -Attribut zu tun.
Also this.full = true auf Kaninchen:
Mal sehen, welche neuen Entdeckungen wir hier gemacht haben. Ein Objekt ruft die übergeordnete Funktion auf, aber dies zeigt immer noch auf das Objekt selbst, das Vererbung ist.
Das von __Proto__ verwiesene Objekt wird als Prototyp bezeichnet, und Tier ist der Prototyp des Kaninchens (Anmerkung des Übersetzers: Dies ist das __Proto__ -Attribut von Kaninchen bezieht sich auf das Prototyp -Attribut des Tieres).
(2) Suche beim Lesen, nicht beim Schreiben
Beim Lesen eines Objekts wie dieser .prop sucht der Interpreter nach Eigenschaften in seinem Prototyp.
Beim Festlegen eines Attributwerts wie diesen. Löschen obj.prop ist ähnlich, es löscht nur die Eigenschaften des Objekts selbst, und die Eigenschaften im Prototyp bleiben intakt.
(3) über Proto
Wenn Sie den Leitfaden lesen, nennen wir hier __Proto__, der im Handbuch als [[Prototyp]] dargestellt wird. Beide Klammern sind wichtig, da es eine andere Eigenschaft namens Prototyp gibt.
2. Object.create, Object.getPrototypeof
__Proto__ ist eine nicht standardmäßige Eigenschaft, die von Chrome/Firefox bereitgestellt wird und in anderen Browsern unsichtbar bleibt.
Alle modernen Browser außer Opera (dh> 9) unterstützen zwei Standardfunktionen, um Prototypprobleme zu behandeln:
Object.Ceate (Prop [, Requisiten])
Erstellen Sie ein leeres Objekt mit dem angegebenen Proto:
var Animal = {ess: true} Rabbit = Objekt.Create (Animal) Alert (Rabbit.eats) // TrueDer obige Code erstellt ein leeres Kaninchenobjekt und der Prototyp ist auf Tier gesetzt
Nachdem das Kaninchenobjekt erstellt wurde, können wir ihm Eigenschaften hinzufügen:
var Animal = {ess: true} Rabbit = Objekt.create (Tier) Rabbit.jumps = trueDer zweite Parameter des Objekts.Creat -Funktion ist optional, wodurch Eigenschaften wie neue Objekte festgelegt werden können. Dies wird aufgrund der Vererbung unserer Beziehung weggelassen.
(1) Object.getPrototypeof (OBJ)
Gibt den Wert von OBJ .__ Proto__ zurück. Diese Funktion ist Standard und kann in Browsern verwendet werden, die nicht direkt auf das __Proto__ -Attribut zugreifen können.
var Animal = {ess: true} Rabbit = Object.create (Animal) Alert (Object.getPrototypeof (Rabbit) === Animal) // TrueModerne Browser ermöglichen das Lesen von __Proto__ -Attributwerten, aber sie können nicht festgelegt werden.
3. Der Prototyp
Es gibt einige gute Cross-Browser-Möglichkeiten, um das __Proto__-Attribut festzulegen, das Konstruktorfunktionen verwendet. erinnern! Jede Funktion erstellt ein Objekt über das neue Schlüsselwort.
Eine Kastanie:
Funktion Rabbit (Name) {this.name = name} var Rabbit = New Rabbit ('John') Alert (Rabbit.Name) // JohnDie neue Operation legt die Eigenschaften des Prototyps auf die Eigenschaft __Proto__ des Kaninchenobjekts fest.
Werfen wir einen Blick auf sein Prinzip, zum Beispiel ein neues Kaninchenobjekt, das Tier erbt.
var Animal = {ess: true} Funktion Rabbit (Name) {this.name = name} Rabbit.Prototype = Animalvar Rabbit = New Rabbit ('John') Alert (Rabbit.eats) // True, weil Rabbit .__ Proto__ == AnimalRabbit.Prototype = Tierwörtliche Mittelwerte: Setzen Sie __Proto__ = Tier für alle von neuen Kaninchen erstellten Objekte
4. Cross-Browser-Objekt.Create (Proto)
Die Funktion von Object.Create (Prop) ist leistungsstark, da sie eine direkte Vererbung aus einem bestimmten Objekt ermöglicht. Es kann durch den folgenden Code simuliert werden:
Funktion inherit (proto) {Funktion f () {} f.prototype = proto return neu f}Inherit (Tier) entspricht genau dem Objekt.Create (Tier), gibt ein leeres Objekt zurück und Objekt .__ Proto__ = Tier.
Eine Kastanie:
var Animal = {ess: true} var rabbit = inherit (tier) alarm (Rabbit.eats) // Truealert (Rabbit.hasownProperty ('ess') // False aus dem PrototypSchauen wir uns an, was sein Prinzip ist:
Funktion Inherit (proto) {Funktion f () {} // (1) f.prototype = proto // (2) RECHTEN SIE NEU F () // (3)} zurück(1) Es wurde eine neue Funktion erstellt, und die Funktion hat keine Attribute darauf gesetzt, sodass "neuer F` ein leeres Objekt erstellt.
(2) `F.Prototype` ist auf Proto eingestellt
(3) `new` f erstellt ein leeres Objekt, das Objekt` __Proto__ = f.prototype`
(4) Bingo! Wir bekommen ein leeres Objekt, das `Proto` erbt
Diese Funktion wird in verschiedenen Bibliotheken und Frameworks häufig verwendet.
Ihre Funktion akzeptiert ein Objekt mit Optionen
/ * Optionen enthalten Menüeinstellungen: Breite, Höhe usw. */Funktionmenü (Optionen) {// ...} Sie möchten bestimmte Optionen Funktionsmenü festlegen (Optionen) {options.width = options.width || 300 // Standardwert einstellen // ...}. . . Das Ändern des Parameterwerts kann jedoch zu falschen Ergebnissen führen, da Optionen im externen Code verwendet werden können. Eine Lösung besteht darin, das Optionsobjekt zu klonen, alle Attribute in ein neues Objekt zu kopieren und es im neuen Objekt zu ändern.
Wie kann ich dieses Problem mit der Vererbung lösen? PS -Optionen können Einstellungen hinzufügen, können jedoch nicht gelöscht werden.
Lösung
Sie können Optionen erben und neue Eigenschaften in der Unterklasse ändern oder hinzufügen.
Funktion Inherit (proto) {Funktion f () {} f.prototype = proto return New F} Funktionmenü (Optionen) {var opts = Inherit (Optionen) opts.width = opts.width || 300 // ...}Alle Operationen sind nur in Unterobjekten gültig. Wenn die Menümethode endet, kann externer Code weiterhin nicht modifizierte Optionen Objekte verwenden. Der Löschvorgang ist hier sehr wichtig. Wenn Breite eine Eigenschaft in einem Prototyp ist, hat die Löschung opts.width keinen Einfluss
5. HasownProperty
Alle Objekte haben eine HasownProperty -Funktion, mit der festgestellt werden kann, ob eine Eigenschaft selbst oder ein Prototyp ist.
Eine Kastanie:
Funktion Rabbit (Name) {this.name = name} rabbit.prototype = {its: true} var rabbit = new Rabbit ('John') Alert (Rabbit.hasownProperty ('ess') // false, in Prototypealt (Rabbit.HasownProperty ('Name') // wahr, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt, im Objekt6. Schleifen mit/ohne ererbte Eigenschaften
für... in Schleifen gibt alle Eigenschaften eines Objekts aus, einschließlich eines eigenen und Prototyps.
Funktion Rabbit (Name) {this.name = name} rabbit.prototype = {iss: true} var rabbit = new Rabbit ('John') für (var p in Kaninchen) {alert (p + "=" + Rabbit [p]) // Ausgibt beide "Namen" und "Ess"}}Verwenden Sie HasownProperty, um die Eigenschaften des Objekts zu filtern:
Funktion Rabbit (Name) {this.name = name} Rabbit.Prototype = {ess: true} var rabbit = new Rabbit ('John') für (var p in Rabbit) {if (! Rabbit.hasownProperty (p)) Fortsetzung // Filter "Ess" -Alert (p + "=" + Rabbit [p] // nur "outters" name "name" name "name" name "name" name "name" name "name" "7. Zusammenfassung
JavaScript implementiert die Vererbung durch ein spezielles Attributproto
Wenn der Interpreter auf die Eigenschaften eines Objekts zugreift und der Interpreter nicht im Objekt finden kann, wird dies weiterhin nach den Funktionseigenschaften suchen, wobei dies auf das Objekt und nicht auf seinen Prototyp verweist.
Zuweisen Sie obj.prop = Wert, löschen Sie obj.prop
Proto verwalten:
Chrome und Firefox können direkt auf das __Proto__ -Attribut des Objekts zugreifen. Die meisten modernen Browser unterstützen den schreibgeschützten Zugriff mit Object.getPrototypeof (OBJ).
Object.create (Proto) kann mit dem angegebenen Proto leere untergeordnete Objekte erzeugen oder über den folgenden Code dieselbe Funktion erreichen:
Funktion inherit (proto) {Funktion f () {} f.prototype = proto return New f ()}Andere Methoden:
für... in Schleifen gibt alle Eigenschaften eines Objekts (einschließlich eines eigenen und Prototyps) und der Prototypkette des Objekts aus.
Wenn eine Eigentumsquote zum Objekt OBJ gehört, gibt Obj.hasownProperty (Prop) wahr, ansonsten falsch.