Erstaunlicherweise wird in keiner der Antworten die Relevanz des Ausführungskontextes in der Scope Chain erwähnt.
Die JavaScript-Engine verpackt den aktuell ausgeführten Code in einen Ausführungskontext. Der Basis-Ausführungskontext ist der globale Ausführungskontext. Jedes Mal, wenn eine neue Funktion aufgerufen wird, wird ein neuer Ausführungskontext erstellt und auf dem Ausführungsstapel abgelegt. Stellen Sie sich einen Stack Frame vor, der in anderen Programmiersprachen auf einem Invocation Stack sitzt. Wer zuletzt kommt, mahlt zuerst. Nun hat jeder Ausführungskontext seine eigene variable Umgebung und äußere Umgebung in JavaScript.
Zur Veranschaulichung möchte ich das folgende Beispiel verwenden.
1) Zunächst wird die Erstellungsphase des globalen Ausführungskontexts eingeleitet. Sowohl die äußere Umgebung als auch die variable Umgebung der lexikalischen Umgebung werden erstellt. Das globale Objekt wird eingerichtet und im Speicher abgelegt, wobei die spezielle Variable "this" auf es verweist. Die Funktion a und ihr Code sowie die Variable myVar mit einem undefinierten Wert werden im Speicher der globalen variablen Umgebung abgelegt. Er wird lediglich mit der Funktion a im Speicher abgelegt.
2) Zweitens ist dies die Ausführungsphase des Ausführungskontexts. myVar ist nicht länger ein undefinierter Wert. Er wird mit dem Wert 1 initialisiert, der in der globalen Variable Environment gespeichert ist. Die Funktion a wird aufgerufen und ein neuer Ausführungskontext wird erstellt.
3) Im Ausführungskontext der Funktion a durchläuft sie die Erstellungs- und Ausführungsphase ihres eigenen Ausführungskontexts. Sie hat ihre eigene äußere Umgebung und ihre variable Umgebung, also ihre eigene lexikalische Umgebung. Die Funktion b und die Variable myVar werden in ihrer variablen Umgebung gespeichert. Diese variable Umgebung unterscheidet sich von der globalen variablen Umgebung. Da die Funktion a lexikalisch (physisch im Code) auf derselben Ebene wie der globale Ausführungskontext angesiedelt ist, ist ihre äußere Umgebung der globale Ausführungskontext. Wenn die Funktion a also auf eine Variable verweist, die sich nicht in ihrer Variablenumgebung befindet, durchsucht sie die Scope Chain und versucht, die Variable in der Variablenumgebung des globalen Ausführungskontexts zu finden.
4) Die Funktion b wird in der Funktion a aufgerufen. Es wird ein neuer Ausführungskontext erstellt. Da er sich lexikalisch in der Funktion a befindet, ist seine äußere Umgebung a. Wenn er also auf myVar verweist, wird er, da myVar nicht in der variablen Umgebung der Funktion b ist, in der variablen Umgebung der Funktion a suchen. Dort wird er gefunden und console.log gibt 2 aus. Befindet sich die Variable jedoch nicht in der Variablenumgebung von Funktion a, so sucht die Scope Chain dort weiter, da die äußere Umgebung von Funktion a der globale Ausführungskontext ist.
5) Nachdem die Funktionen b und a ausgeführt wurden, werden sie aus dem Ausführungsstapel entfernt. Die Single-Thread-JavaScript-Engine setzt die Ausführung im globalen Ausführungskontext fort. Sie ruft die Funktion b auf. Es gibt jedoch keine Funktion b in der globalen Variablenumgebung und es gibt keine andere äußere Umgebung, die im globalen Ausführungskontext zu suchen wäre. Daher wird von der JavaScript-Engine eine Ausnahme ausgelöst.
function a(){
function b(){
console.log(myVar);
}
var myVar = 2;
b();
}
var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined
Das folgende Beispiel zeigt die Scope Chain in Aktion. In der Variablenumgebung des Ausführungskontexts der Funktion b gibt es keine myVar. Also wird die äußere Umgebung der Funktion a durchsucht. Die Funktion a hat myVar ebenfalls nicht in ihrer variablen Umgebung. Die Engine durchsucht also die äußere Umgebung der Funktion a, die die äußere Umgebung des globalen Ausführungskontexts ist, und myVar ist dort definiert. Daher wird in console.log die Zahl 1 ausgegeben.
function a(){
function b(){
console.log(myVar);
}
b();
}
var myVar = 1;
a();
> 1
Der Ausführungskontext und die damit verbundene lexikalische Umgebung, einschließlich äußerer Umgebung und variabler Umgebung, ermöglichen das Scoping von Variablen in JavaScript. Selbst wenn Sie dieselbe Funktion mehrmals aufrufen, wird für jeden Aufruf ein eigener Ausführungskontext erstellt. Jeder Ausführungskontext hat also seine eigene Kopie der Variablen in seiner Variablenumgebung. Es gibt keine gemeinsame Nutzung von Variablen.