Analyse einer Interviewfrage zur Javascript-Prototypkette (Details)
Der Inhalt dieses Artikels ist eine (detaillierte) Analyse einer Interviewfrage zur JavaScript-Prototypenkette. Ich hoffe, dass er für Sie hilfreich ist.
Vor den Basics sind alle Fähigkeiten umsonst.
Die Frage sieht so aus
Erfordert das Schreiben der Ausgabe der Konsole.
function Parent() { this.a = 1; this.b = [1, 2, this.a]; this.c = { demo: 5 }; this.show = function () { console.log(this.a , this.b , this.c.demo ); } } function Child() { this.a = 2; this.change = function () { this.b.push(this.a); this.a = this.b.length; this.c.demo = this.a++; } } Child.prototype = new Parent(); var parent = new Parent(); var child1 = new Child(); var child2 = new Child(); child1.a = 11; child2.a = 12; parent.show(); child1.show(); child2.show(); child1.change(); child2.change(); parent.show(); child1.show(); child2.show();
Die an der Frage beteiligten Wissenspunkte
dies verweist auf die
Prototyp-Maschine-Prototyp-Kette
Vererbung der Klasse
für primitive Typen und Referenztypen Der Unterschied
Jeder Wissenspunkt kann für separate Spezialforschung herausgenommen werden.
Details zu den zur Lösung des Problems erforderlichen Wissenspunkten
1 Der Konstruktor verfügt über ein Prototypattribut, das auf das Prototypobjekt des Konstruktors verweist Die Instanz teilt sich das gleiche A-Prototypobjekt.
2. Wenn eine Instanz generiert wird, wird ein neuer Heap-Speicher im Speicher generiert, da diese andere Instanzen belegen im Heapspeicher und beeinflussen sich nicht gegenseitig ;
3 Jede Instanz hat einen impliziten Prototyp __proto__, der auf das Prototypobjekt des Konstruktors verweist Situationen umfassen Folgendes:
4.1 Wenn es als Objektmethode aufgerufen wird, zeigt es auf denjenigen, der es aufruft (diese Frage betrifft hauptsächlich diesen Artikel)
4.2 Wenn es als Funktion aufgerufen wird, zeigt es auf die globales Variablenfenster der obersten Ebene
4.3 Als Konstruktor Wenn eine Funktion aufgerufen wird, also wenn der neue Operator eine Instanz generiert, zeigt diese im Konstruktor auf die Instanz
4.4 Im Aufruf- und Anwendungsmethoden, die Bindung des angegebenen This wird als angegebener Kontext angezeigt
5. Literal Quantitative Methode (Es gibt auch Informationen, die Literal in direkte Quantität übersetzen. Ich persönlich denke, dass die letztere Übersetzung tatsächlich mehr ist (intuitiv und anschaulich). Beim Zuweisen von Objekten und Arrays (das Wesentliche von Arrays sind auch Objekte) werden alle Ressourcen im Heapspeicher generiert Adresse der Ressource.
6. Die Suchregeln der Prototypenkette folgen dem Prinzip des kürzesten Pfades, d Wenn die Instanz selbst und die gesuchte Eigenschaft nicht in der gesamten Prototypenkette vorhanden sind, wird undefiniert zurückgegeben.
Der detaillierte Unterschied zwischen Zuweisungsanweisungen für die Zuweisung von primitiven Werten und den Referenztyp Aufgabe.
Beginnen Sie mit der Analyse der Frage
1.parent.show()
Es gibt im Grunde nichts zu erklären.
Sie können die Antwort erhalten, indem Sie direkt den Wert nehmen1 [1,2,1] 5
;
2.child1.show()
Child
Der Konstruktor zeigte ursprünglich auf Child
. In der Frage zeigte das Prototypobjekt der Klasse
auf eine Instanz der Klasse Child
in der objektorientierten JavaScript-Programmierung 🎜>Eine der VererbungsmethodenParent
. Hierbei ist zu beachten, dass auf die Instanz von Child.prototype
verweist, nicht auf die Klasse Parent
parent
Parent
. Sie können die Antwort direkt auf der Konsole ausgeben, um 11 [1,2,1] 5
Was hier verwirrend ist, ist, warum die letzte Spalte des Arrays, auf das this.b zeigt,
statt ist >
1
11
sucht dann nach this.b, weil child1 kein b-Attribut hat, daher wird das b-Attribut des übergeordneten Elements entlang der Prototypenkette abgerufen. Die ersten beiden Elemente sind Konstanten, was nichts aussagt Das letzte Element des Arrays ist eine Referenz, und der Zeiger hier ist kein dynamischer Zeiger, da er während des neuen Parent()-Schritts einmal ausgeführt wurde und bestimmt ist, auf die Ressource zu zeigen, auf die er zeigt parent.a, die Ressource, auf die das Attribut a in child1.__proto__ zeigt, also der Wert 1.
Es ist zu beachten, dass:
Aus Codesicht ist das child1.__proto__. b-Array ist Die drei Elemente zeigen auf child1.__proto__.a. Wenn wir also zu diesem Zeitpunkt den Wert von child1.__proto__.a ändern, wirkt sich dies auf das Ergebnis von child1.show() aus:
-
Die Antwort ist, dass es keine Auswirkungen hat. Warum haben Attribute, die auf dieselbe Adresse zu verweisen scheinen, unterschiedliche Werte? Denn wenn die übergeordnete Instanz generiert wird, zeigt this.a auf einen primitiven Wert 2, sodass dem dritten Element in this.b tatsächlich ein primitiver Wert zugewiesen wird, sodass es auf den ersten Blick wie eine Referenztypzuweisung aussieht, dies aber nicht der Fall ist. . Durch die Zuweisung primitiver Werte wird neuer Speicherplatz geöffnet, sodass die Werte von this.a und this.b[2] gleich sind, aber auf unterschiedliche Adressen im Heap-Speicher verweisen. Ausführlichere Erklärungen finden Sie in den empfohlenen Blogbeiträgen in [Erweiterte Lektüre].
2. Wie kann das dritte Element des Arrays child1.__proto__.b auch 11 ausgeben?
Weil in In der Definition der übergeordneten Klasse zeigt das dritte Element des b-Attributarrays auf den Wert des a-Attributs. Dies bedeutet, dass vor der Instanziierung des übergeordneten Elements dynamisch auf diese Referenz verwiesen wird, solange der Wert von this.a im Wenn die Klassendefinition geändert wird, bevor das übergeordnete Element instanziiert wird, können Sie den gewünschten Effekt erzielen. Wenn es im übergeordneten Element instanziiert wurde, können Sie nur den Wert des *.b[2]-Attributs explizit ändern.
Ändern Sie es nach der Instanziierung
Eine andere Möglichkeit besteht darin, die Get/Set-Methode für das a-Attribut festzulegen. Ja, immer wenn sich der Wert des a-Attributs ändert, wird der Wert von b[2] synchron geändert . Der Code und die laufenden Ergebnisse lauten wie folgt:
3.child2. show( ) Wenn Sie die obige Erklärung verstanden haben, können Sie die Antwort mit der gleichen Methode hier erhalten: 12 [1,2,1] 5
Dann wird der Code ausgeführt: child1.change(); child2.change();
4.parent.show()
parent ist eine Instanz der Parent-Klasse und Child.prorotype zeigt auf eine andere Instanz der Parent-Klasse. Die beiden sind zwei Ressourcen im Heap-Speicher und wirken sich nicht gegenseitig aus, sodass die oben genannten Vorgänge keine Auswirkungen auf die übergeordnete Klasse haben Beispiel, und die
Ausgabeergebnisse bleiben unverändert: 1 [1,2,1] 5;5.child1.show(),child2.show()
Welche Änderungen sind aufgetreten, nachdem child1 die Methode change() ausgeführt hat?
this.b. push(this.a)
Aufgrund der dynamischen Zeigeeigenschaften von this zeigt this.b auf das b-Array in Child.prototype und this.a zeigt auf das a-Attribut von child1, also Child.prototype. b wird zu [1,2,1,11];
this.a = this.b.length
Die Punkte von this.a und this.b in this Die Aussage ist dasselbe wie Der vorherige Satz ist konsistent, daher ist das Ergebnis, dass child1.a zu 4;
this.c.demo = this.a++Da die eigenen Attribute von child1 nicht c sind, verweist this.c hier auf Child.prototype.c. Der Wert von this.a ist
4, was ein primitiver Typ ist Die Zuweisungsoperation weist den Wert direkt Child.prototype.c zu. Das Ergebnis der Demo ist 4, und this.a erhöht sich dann auf 5(4 + 1 = 5).
Daher wirken sich alle Anweisungen in , die sich auf das Prototypobjekt auswirken, auf das endgültige Ausgabeergebnis von child2.change()
child1
this.b.push(this.a)Aufgrund der dynamischen Zeigeeigenschaften davon zeigt this.b auf Für das b-Array auf Child.prototype zeigt this.a auf das a-Attribut von child2, sodass Child.prototype.b zu
[1,2,1,11,12];this.a = this.b.length
Die Richtungen von this.a und this.b in dieser Anweisung stimmen mit dem vorherigen Satz überein, sodass das Ergebnis ist, dass child2.a 5 wird;
this.c.demo = this.a++
Da das eigene Attribut von child2 dies nicht tut Wenn Sie das C-Attribut haben, zeigt this.c hier auf Child.prototype.c, sodass das Ausführungsergebnis Child ist. Der Wert von .prototype.c.demo ändert sich in den Wert 5 von child2.a, und child2.a wird schließlich auf erhöht 6 (5 + 1 = 6). Als nächstes führen Sie den Ausgabebefehl aus und das Endergebnis wird ausgegeben:
child2.show():6 [1,2,1,11 ,12] 5
Erweitertes DenkenAls ich war Bei der Lösung des Problems habe ich einen Fehler in this.c.demo = this.a++ gemacht. Ich dachte, dass hier eine Referenz übergeben würde, aber tatsächlich wurde ein Wert übergeben. Nach der Analyse verstehen wir das, weil this.a darauf verweist Wenn Sie einen Originalwert angeben, entspricht dies der Zuweisung des Originalwerts zum Objektattribut, sodass der Wert von child.c.demo nach der Zuweisung nicht mehr von Änderungen in child.a beeinflusst wird. Wenn child.a ein Referenztyp ist, wie sieht das Ergebnis aus?
Nach der Ausführung werden wir feststellen, dass der Wert von Child.prototype.c folgt Der Wert von child1.a ändert sich mit Änderungen, da der Wert von child1.a zu diesem Zeitpunkt ein Referenztyp ist und der Zuweisungsprozess dazu führt, dass Child.prototype.c und child1.a auf die Speicherplatzadresse derselben Ressource verweisen . Eine ausführlichere Erläuterung der Originaltypen und Referenztypen finden Sie im Blog „Erweiterte Lektüre“ am Ende dieses Artikels. Ernte und Reflexion
Das obige ist der detaillierte Inhalt vonAnalyse einer Interviewfrage zur Javascript-Prototypkette (Details). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Häufig gestellte Fragen und Lösungen für das Ticket-Ticket-Ticket-Ticket in Front-End im Front-End-Entwicklungsdruck ist der Ticketdruck eine häufige Voraussetzung. Viele Entwickler implementieren jedoch ...

Es gibt kein absolutes Gehalt für Python- und JavaScript -Entwickler, je nach Fähigkeiten und Branchenbedürfnissen. 1. Python kann mehr in Datenwissenschaft und maschinellem Lernen bezahlt werden. 2. JavaScript hat eine große Nachfrage in der Entwicklung von Front-End- und Full-Stack-Entwicklung, und sein Gehalt ist auch beträchtlich. 3. Einflussfaktoren umfassen Erfahrung, geografische Standort, Unternehmensgröße und spezifische Fähigkeiten.

JavaScript ist der Eckpfeiler der modernen Webentwicklung. Zu den Hauptfunktionen gehören eine ereignisorientierte Programmierung, die Erzeugung der dynamischen Inhalte und die asynchrone Programmierung. 1) Ereignisgesteuerte Programmierung ermöglicht es Webseiten, sich dynamisch entsprechend den Benutzeroperationen zu ändern. 2) Die dynamische Inhaltsgenerierung ermöglicht die Anpassung der Seiteninhalte gemäß den Bedingungen. 3) Asynchrone Programmierung stellt sicher, dass die Benutzeroberfläche nicht blockiert ist. JavaScript wird häufig in der Webinteraktion, der einseitigen Anwendung und der serverseitigen Entwicklung verwendet, wodurch die Flexibilität der Benutzererfahrung und die plattformübergreifende Entwicklung erheblich verbessert wird.

Wie fusioniere ich Array -Elemente mit derselben ID in ein Objekt in JavaScript? Bei der Verarbeitung von Daten begegnen wir häufig die Notwendigkeit, dieselbe ID zu haben ...

Diskussion über die Realisierung von Parallaxe -Scrolling- und Elementanimationseffekten in diesem Artikel wird untersuchen, wie die offizielle Website der Shiseeido -Website (https://www.shiseeido.co.jp/sb/wonderland/) ähnlich ist ...

JavaScript zu lernen ist nicht schwierig, aber es ist schwierig. 1) Verstehen Sie grundlegende Konzepte wie Variablen, Datentypen, Funktionen usw. 2) Beherrschen Sie die asynchrone Programmierung und implementieren Sie sie durch Ereignisschleifen. 3) Verwenden Sie DOM -Operationen und versprechen Sie, asynchrone Anfragen zu bearbeiten. 4) Vermeiden Sie häufige Fehler und verwenden Sie Debugging -Techniken. 5) Die Leistung optimieren und Best Practices befolgen.

Eingehende Diskussion der Ursachen des Unterschieds in der Konsole.log-Ausgabe. In diesem Artikel wird die Unterschiede in den Ausgabeergebnissen der Konsolenfunktion in einem Code analysiert und die Gründe dafür erläutert. � ...

Erforschen Sie die Implementierung der Funktion des Bedien- und Drop-Einstellungsfunktion der Panel ähnlich wie VSCODE im Front-End. In der Front-End-Entwicklung wird VSCODE ähnlich wie VSCODE implementiert ...
