Heim  >  Artikel  >  Web-Frontend  >  Analyse einer Interviewfrage zur Javascript-Prototypkette (Details)

Analyse einer Interviewfrage zur Javascript-Prototypkette (Details)

不言
不言Original
2018-09-19 17:12:065561Durchsuche

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
Analyse einer Interviewfrage zur Javascript-Prototypkette (Details). 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 ParentparentParent. Sie können die Antwort direkt auf der Konsole ausgeben, um
Analyse einer Interviewfrage zur Javascript-Prototypkette (Details)
11 [1,2,1] 5Was hier verwirrend ist, ist, warum die letzte Spalte des Arrays, auf das this.b zeigt,
statt Analyse einer Interviewfrage zur Javascript-Prototypkette (Details) ist >

steht an erster Stelle. Schauen Sie sich an, wie child1 aussieht:

111

Wenn die Methode child1.show() ausgeführt wird, da child1 als Instanz von Child das Attribut hat a, also zeigt this.a in der show()-Methode direkt auf den Wert dieses Attributs, der 11 ist, anstatt entlang der Prototypenkette fortzufahren, um das a-Attribut für das Objekt zu erhalten, auf das __proto__

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.
Analyse einer Interviewfrage zur Javascript-Prototypkette (Details)

Erweitertes Denken

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:

  1. 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].

    Analyse einer Interviewfrage zur Javascript-Prototypkette (Details)

    2. Wie kann das dritte Element des Arrays child1.__proto__.b auch 11 ausgeben?


    Ändern Sie es nach der Instanziierung

    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.
Synchronisierung der Get/Set-Methode

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:



  • Analyse einer Interviewfrage zur Javascript-Prototypkette (Details)
    3.child2. show( )Analyse einer Interviewfrage zur Javascript-Prototypkette (Details)

  • 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).

Dann führt child2 die Methode change() aus und child2 und child1 sind beide Instanzen der Child-Klasse, sodass ihre Prototypketten auf dasselbe Prototypobjekt Child.prototype verweisen, das dieselbe übergeordnete Instanz ist,

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:

child1.show():5 [1,2,1, 11,12] 5


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?

Wir nehmen einige Änderungen am Quellcode vor und verweisen child.a auf ein Objekt (d. h. einen Referenztyp):


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.
Analyse einer Interviewfrage zur Javascript-Prototypkette (Details)Ernte und Reflexion

1. Grundwissen besteht von Natur aus aus verstreuten Details und muss mit einer ganzheitlichen Einstellung erlernt werden.

2. Grundkenntnisse sind das Langweiligste, und es ist auch das, was die Kluft zwischen den Menschen wirklich vergrößert. Es ist auch die Schwelle, die man überschreiten muss, wenn man eine große Fabrik betreten möchte. Es ist aber nicht wichtig dringend. Wir sind auch Neulinge, die nach 3-5 Jahren zu Front-End-Architekten werden. Manche Leute werden auch nach 3-5 Jahren immer noch endlose neue Frameworks verwenden, um Ereignisse an Schaltflächen zu binden zum Einsetzen. Meistens ist daran nichts auszusetzen. Die Basics sind wichtig! Sehr wichtig! Sehr wichtig!

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn