Einführung
1. Referenztyp
Der Referenztyp ist ein interner Typ in JavaScript. Es wird hauptsächlich als Referenz verwendet und ersetzt eine Variable oder Funktion. Wenn der tatsächliche Wert benötigt wird, kann der tatsächliche Wert natürlich dadurch ermittelt werden.
2. Struktur des Referenztyps
Der Wert eines Referenztyps besteht aus zwei Teilen, zu denen das Objekt gehört, auf das der Wert des Referenztyps verweist. Hier nennen wir es Basis, und der andere ist der Objektname des Objekts, auf das in Basis verwiesen wird . Im Pseudocode dargestellt:
Kopieren Sie den Codecode wie folgt:
var valueOfReferenceType = {
Basis: <Basisobjekt>,
Eigenschaftsname: <Eigenschaftsname>
};
3. Nutzungsszenarien
Es gibt zwei Verwendungsszenarien für Referenztypen:
(1) Bei der Verarbeitung einer Kennung
Bezeichner sind Variablennamen, Funktionsnamen, Funktionsparameternamen und unbekannte Eigenschaftsnamen in globalen Objekten.
(2) Bei der Verarbeitung eines Eigenschaftszugriffs
Kopieren Sie den Codecode wie folgt:
var foo = 10;
Funktionsleiste( ){}
In den Zwischenergebnissen der Operation entspricht der Referenztyp
Kopieren Sie den Codecode wie folgt:
var fooReference = {
Basis: global,
Eigenschaftsname: 'foo'
};
var barReference = {
Basis: global,
Eigenschaftsname: 'bar'
};
Es ist hier noch notwendig, die Basis zu erklären. In JavaScript haben alle Objekte oder Funktionen ihre eigenen Objekte. Jeder, der meinen vorherigen Artikel gelesen hat, weiß, dass es in jedem Ausführungskontext ein Variablenobjekt gibt, um die Variablen oder Funktionen in diesem Ausführungskontext zu verwalten . .
Wenn es also um Bezeichner geht:
Im globalen Kontext versteht es sich von selbst, dass base === globalVO === gloabal
Im Ausführungskontext der Funktion gilt base === VO/AO
Die Eigenschaften des Verarbeitungsobjekts sind jedoch:
Das ist noch einfacher: base === owerObject
4. Ermitteln Sie den wahren Wert des Referenztyps
Wie wir eingangs sagten, ist ein Referenztyp nur eine Referenz, speichert jedoch nicht den tatsächlichen Wert. Wenn der tatsächliche Wert benötigt wird, kann er durch eine Reihe interner Algorithmen ermittelt werden. Wir können diesen Algorithmus mit einfachem Pseudocode beschreiben:
Kopieren Sie den Codecode wie folgt:
Funktion GetValue(value) {
if (Type(value) != Reference) {
Rückgabewert;
}
var base = GetBase(value);
if (base === null) {
throw new ReferenceError;
}
return base.[[Get]](GetPropertyName(value));
}
Die interne Methode [[Get]] gibt den wahren Wert der Objekteigenschaften zurück, einschließlich der Analyse geerbter Eigenschaften in der Prototypenkette. Über GetValue können wir also auch problemlos den tatsächlichen Wert des Referenztyps ermitteln. Zum Beispiel:
Kopieren Sie den Codecode wie folgt:
GetValue(fooReference); // 10
GetValue(barReference); // Funktionsobjekt „bar“
Wann müssen wir also den tatsächlichen Wert des Referenztyps ermitteln?
Wenn ein Referenztyp zugewiesen, an einer Operation beteiligt oder aufgerufen werden muss, muss im Allgemeinen der tatsächliche Wert über die GetValue-Methode abgerufen werden. (Hinweis: Das über GetValue erhaltene Objekt ist kein Referenztyp mehr.)
Die Beziehung zwischen Referenztypen und this
Der Referenztyp hängt hauptsächlich eng mit diesem Punkt im Funktionskontext zusammen und sieht zu verschiedenen Zeiten ganz anders aus. Daher führen wir den Referenztyp ein, um die Leistung dieses Punkts im Funktionskontext konkret zu erläutern.
Die allgemeinen Regeln zur Bestimmung des Werts davon im Funktionskontext lauten wie folgt:
Im Kontext einer Funktion wird dies vom Aufrufer bereitgestellt und hängt davon ab, wie die Funktion aufgerufen wird. Wenn die linke Seite der aufrufenden Klammer () ein Wert vom Referenztyp ist, wird dieser auf das Basisobjekt des Referenztypwerts gesetzt. In anderen Fällen (alle anderen Eigenschaften, die vom Referenztyp abweichen) ist dieser Wert null . Es gibt jedoch keine tatsächliche Situation, in der der Wert von this null ist, denn wenn der Wert von this null ist, wird sein Wert implizit in ein globales Objekt konvertiert. Hinweis: In der fünften Ausgabe von ECMAScript wird die Konvertierung in globale Variablen nicht mehr erzwungen, sondern undefiniert zugewiesen.
Im Folgenden besprechen wir drei Situationen basierend auf dem Unterschied auf der linken Seite der aufrufenden Klammer:
(1) Die linke Seite der aufrufenden Klammer ist der Wert des Referenztyps
Dies erfordert nicht allzu viel Analyse. Das Basisobjekt ist der Wert davon. Wenn es unter einer globalen Variablen deklariert ist, zeigt es auf das globale Objekt.
Kopieren Sie den Codecode wie folgt:
var myObject = {
foo : function(){
console.log(this);
}
}
myObject.foo(); //Es besteht kein Zweifel, dass die Basis von foo myObject ist, daher zeigt dies in der foo-Methode auf myObject.
(2) Die linke Seite der aufrufenden Klammer ist ein Referenztypwert, aber dieser Wert ist null
Kopieren Sie den Codecode wie folgt:
Funktion myFunction() {
var foo = function(){
console.log(this);
}
foo(); //AO.foo() => null.foo()
}
myFunction(); //Ausgabe: Fenster {oben: Fenster, Fenster: Fenster...}
Wenn eine interne Funktion aufgerufen wird, sollte die Basis der internen Funktion das aktive Objekt (OA) im aktuellen Ausführungskontext sein. Wenn OA als Basis verwendet wird, wird dies jedoch sicherlich nicht als Null behandelt Erlauben Sie, dass dies null ist, die gesamte Basis wird auf das globale Objekt gesetzt (dies ist die Ursache des Entwurfsfehlers im vorherigen Aufrufmuster dieser Funktion). In diesem Fall zeigt dies also auf das globale Objekt.
(3) Rufen Sie den Wert auf der linken Seite der Klammer auf, der kein Referenztyp ist
Kopieren Sie den Codecode wie folgt:
//Einfaches Beispiel
(Funktion () {
console.log(this); // null => global
})();
//Ein komplexeres Beispiel
var foo = {
bar: Funktion () {
console.log(this);
}
};
foo.bar(); // Referenz, OK => foo
(foo.bar)(); // Referenz, OK => foo
(foo.bar = foo.bar)(); // global
(false || foo.bar)(); // global
(foo.bar, foo.bar)(); // global
Wenn die linke Seite der aufrufenden Klammer kein Referenztyp, sondern ein anderer Typ ist, wird dieser automatisch auf null gesetzt und das Ergebnis ist das globale Objekt.
Im ersten Beispiel hat die unmittelbare Funktion einen Ausdruck auf der linken Seite der Funktionsaufrufklammer, keine Referenz.
Das zweite Beispiel ist viel komplizierter. Lassen Sie es uns einzeln analysieren:
foo.bar(), daran besteht kein Zweifel, die Basis ist foo und dies zeigt auf foo.
(foo.bar)(), hier wird eine Klammer verwendet, die als Gruppierungssymbol fungiert, dh den Referenztyp nicht dazu zwingt, die GetValue-Methode auszuführen, und das Ausführungsergebnis ist genau das gleiche wie oben.
Die nächsten drei in Klammern sind Zuweisungsoperationen oder Operationen und Kommaoperationen. Sie alle zwingen den Referenztyp, die GetValue-Methode auszuführen und dadurch ein Funktionsobjekt zurückzugeben. Auf diese Weise ist die linke Seite der Klammer des Funktionsaufrufs kein Referenztyp mehr, sondern zeigt auf das globale Objekt.
Zusammenfassen
Was Referenztypen betrifft, weiß ich eigentlich nicht viel darüber. Um das Wertprinzip im Funktionsaufrufmodus zu erklären, habe ich eine spezielle Analyse durchgeführt Unglaublich, ich habe immer gedacht, dass es eine Beziehung zwischen Referenztypen und Referenzwert geben sollte. Es wird jedoch nur in Bolg verwendet, um das zu verstehen. Ob es zuvor eine Beziehung zwischen den beiden gab und wenn es eine Beziehung gab, um welche Art von Beziehung es sich handelte, muss ich noch weiter studieren und erforschen.
Ich hoffe, Sie können mehr kommunizieren. Dafür möchte ich Onkel Tom danken.