Vorwort
Ich habe eine solche Frage auf Segmentfault gesehen:
var f = function () {}; Object.Prototype.a = function () {}; Function.prototype.b = function () {}; var f = new f ();F: Kann F A und B erhalten? Was ist das Prinzip?
Auf den ersten Blick war ich wirklich verwirrt. Nach sorgfältiger Studie stellte ich fest, dass ich den Prototyp immer noch nicht gründlich verstand, also fasste ich ihn zusammen und füllte ein Loch aus ~
Funktion und Objekt
Bevor Sie das Problem lösen, sprechen wir über den Prototyp, die Prototypkette und die Beziehung zwischen Funktion und Objekt, die auch im Mittelpunkt dieses Artikels steht.
Prototyp
Beim Erstellen einer Funktion wird ein Prototypobjekt automatisch dafür erstellt, auf das über die Prototyp -Eigenschaft der Funktion zugegriffen werden kann.
Erstellen Sie ein Instanzobjekt des Konstruktors, das einen Zeiger (interne Eigenschaft) enthält und auf das Prototypobjekt des Konstruktors verweist. ECMA-262 Die 5. Ausgabe dieses Zeigers heißt [[Prototyp]]. Obwohl es in Skripten, Firefox, Safari und Chrom keine Standardmethode gibt, um eine Eigenschaft __proproto__ auf jedem Objekt zuzugreifen, um auf das Prototypobjekt ihres Konstruktors zuzugreifen.
Lassen Sie mich noch einmal etwas Wichtiges sagen:
Der Konstruktor greift über die Prototyp -Eigenschaft auf das Prototypobjekt zu.
Das Instanzobjekt greift über das interne Attribut [[[Prototyp]] auf das Prototypobjekt zu, und der Browser implementiert das Attribut _Proto_ für das Instanzobjekt, um auf das Prototyp -Objekt zuzugreifen.
var f = function () {}; var f = new f (); // unter der Annahme, dass das Prototyp -Objekt von f P ist, dann // f.prototype === p; // f .__ proto__ === p;Wieder wiederholen. . Der Prototyp bezieht sich auf die Beziehung zwischen dem Konstruktor und dem Prototypobjekt, und __Proto__ bezieht sich auf die Beziehung zwischen dem Instanzobjekt und dem Prototypobjekt.
Prototypkette
Klasse A erbt B, B erbt C ... Tatsächlich gibt es ein Prototypobjekt mit einem Zeiger, der auf B im Prototypobjekt von A zeigt, und ein Prototypobjekt mit einem Zeiger, der im Prototyp -Objekt auf C zeigt ... Beachten Sie, dass es sich um die Verbindung zwischen den Prototyp -Objekten handelt. Es gibt keine Beziehung zwischen den drei Konstruktoren von ABC, daher wird es als "Prototyp -Kette" bezeichnet ~ ~
Angenommen, A ist ein Instanzobjekt von A, ist die Prototypkette von A in der lila Linie in der folgenden Abbildung dargestellt, und die orangefarbene Linie verbindet den Konstruktor und sein Prototypobjekt.
Wie aus der Abbildung ersichtlich ist, ist das Ende der Prototypkette Object.Prototyp .__ proto__ dh null. Wenn Sie nach einer Eigenschaft oder Methode von A suchen, suchen Sie zunächst, ob A selbst hat oder nicht. Wenn nicht, suchen Sie entlang der Prototypkette, bis sie gefunden wurde oder schließlich nach Null zu undefiniert ist.
Funktion und Objekt
Die Beziehung zwischen Funktion und Objekt ist ein bisschen verwirrt:
Objekt ist ein Konstruktor. Da es sich um eine Funktion handelt, ist es das Instanzobjekt der Funktion; Funktion ist ein Konstruktor, aber Funktion.Prototyp ist ein Objekt. Da es sich um ein Objekt handelt, ist es das Instanzobjekt des Objekts.
Alle Objekte sind Instanzen des Objekts, und alle Funktionen sind Funktionen der Funktion.
Das Objekt ist eine Instanz der Funktion und Funktion. Prototyp ist eine Instanz des Objekts.
Die Beziehung zwischen den beiden ist in der folgenden Abbildung dargestellt.
Wie zu sehen ist, hat Objekt als Konstruktor das Prototypattribut auf Object.Prototyp und als Instanzobjekt hat es das Objekt .__ Proto__ zeigt auf Funktion.Prototyp. Funktion ist ein Konstruktor, es hat ein Prototyp -Attribut, das auf Funktion zeigt. Prototyp und Funktion ist eine Funktion, und es ist auch eine Instanz der Funktion, sodass es Funktion hat .__ proto__, der auf die Funktion hinweist.
Es kann unter der Chromkonsole verifiziert werden, wie in der Abbildung gezeigt.
Analyse der ursprünglichen Frage
Der beste Weg, um das Problem der Prototypkette zu lösen, besteht darin, ein Bild zu zeichnen. Nach der vorherigen Analyse sollte dieses Bild kein Problem sein, wie folgt ~
Die Prototyp -Kette von F wird von einer blauen Linie gezeichnet, sodass F auf A zugreifen kann, aber B kann nicht zugreifen.
Wenn Sie kein Bild zeichnen, denken Sie vielleicht, dass F zugreifen kann b. Es mag so sein, dass F.Prototype auf function.Prototypen verweist, aber tatsächlich ist F.Prototype eher ein Objekt als eine Funktion, sodass sein Prototyp -Objekt keine Funktion ist.
Daher sollten Sie ein Bild zeichnen, wenn das Problem der Prototypketten ~ ist
Erweitertes Thema
In der obigen Frage kann F nur auf A zugreifen, aber nicht b. Aber f kann sowohl auf A als auch b zugreifen. Wenn Sie die Frage an Folgendes ändern, was ist das Ergebnis von FB ()? Warum? Sie können darüber nachdenken ~
var f = function () {}; Object.Prototype.a = function () {}; Function.prototype.b = function () {console.log ('f .__ proto__')}; F.Prototype.b = function () {console.log ('F.Prototyp');};Zusammenfassen
Haben Sie nach dem Lesen eine besondere Funktion der Funktion gefunden?
Für ein allgemeines Objekt gibt es nur ein __Proto__ -Attribut zum Zugriff auf das Prototypobjekt seines Konstruktors, und für eine Funktion ist es sowohl eine Funktion als auch ein Objekt.
Als Funktion wird es mit einem Prototyp -Attribut geboren, das auf den Namen der Prototyp -Objektfunktion hinweist.
Als Instanzobjekt der Funktion hat es das __Proto__ -Attribut, das auf function.prototype zeigt
Normalerweise weisen diese beiden Eigenschaften auf zwei Objekte hin, aber beide Eigenschaften der Funktionseigenschaften weisen auf die gleiche hin, die beide auf Funktion weisen.
Für die Funktion a () werden die Methoden in A.Prototype für den Aufruf an sein Instanzobjekt und nicht von selbst verwendet. Wenn A als Fall ausgeführt wird, werden die Methoden in einem .__ -Proto__ aufgerufen. Mit anderen Worten, wenn als Konstruktor verwendet wird, wird die A. -Prototyp -Kette genommen und die Methoden und Attribute werden ihren Beispielen zugeordnet. Wenn als Objekt verwendet wird, wird die a .__ Proto__ -Kette genommen. In verschiedenen Szenarien ist es nicht falsch, seine Identität zu unterscheiden.
Nach dem gesamten Artikel habe ich das Gefühl, dass das, was ich gesagt habe, ziemlich nervig ist ... Bitte korrigieren Sie mich, wenn es Mängel gibt. Was die Frage angeht, weiß ich wirklich nicht, wie ich es nennen soll. .
Möge dieser Artikel Ihnen einige Gewinne bringen, nachdem Sie ihn gelesen haben ~ ^_ ^
Vielen Dank für Ihre Unterstützung für diese Website. Wir werden in Zukunft weiterhin relevante Informationen aktualisieren, um Ihnen dabei zu helfen, diesen Teil des Wissens zu lernen und zu verstehen!