Ich kenne den Unterschied zwischen let und var. let blockiert den Gültigkeitsbereich und var ist der Funktionsumfang.
%Vor% Ich weiß, wie das obige Code-Snippet funktioniert ( console.log(i)
wird zu der Zeit ausgeführt, wenn der Wert von i 3 ist, weil der Geltungsbereich von i global ist).
Aber
%Vor% Das obige Code-Snippet verwirrte mich. nach mir sollte es Reference Error werfen (weil die Zeit, wenn console.log(i)
ausgeführt wird, wird der Wert von i im globalen Bereich nicht im lokalen Bereich aussehen, und ich bin nicht deklarieren / definiert in globalen. so sollte es Referenzfehler geben.)
Wer kann erklären, wie die 2. Schleife für die Runtime funktioniert?
Das zweite Beispiel (mit let
) funktioniert, weil eine Funktion über alle Variablen geschlossen wird, die sich bei der Deklaration im Gültigkeitsbereich befinden. Bei jeder Wiederholung der for-Schleife wird eine neue Variable mit let
erstellt, die Funktion im Timeout schließt sich über der Variable und behält eine Referenz bei. Wenn die Funktion nach der Zeitüberschreitung dereferenziert wird, sind es auch ihre Abschlussvariablen.
Siehe Wie funktionieren JavaScript-Schließungen für weitere Informationen zum Schließen von Funktionen.
Dies ist die Magie der Schließung. In der Seite Ihrer Schleife
%Vor%Sie deklarieren eine Funktion
%Vor%Zusätzlich deklariert die Schleife selbst einen Block
%Vor% Variablen, die mit let
definiert sind, sind Blockbereiche.
Aufgrund von Schließung hat die Funktion, die Sie innerhalb der Schleife deklarieren, Zugriff auf alle die Variablen, die in ihrem Gültigkeitsbereich und ihren übergeordneten Bereichen deklariert sind , bis sie als Garbage Collection erfasst wird.
Eine Schließung ist die Kombination einer Funktion und der lexikalischen Umgebung innerhalb dessen diese Funktion deklariert wurde. Diese Umgebung besteht aus alle lokalen Variablen, die zum Zeitpunkt der Schließung in Geltung waren wurde erstellt.
Die Variable i
ist in-scope , wenn die von setTimeout
verwendeten Funktionen erstellt werden. Die i
, auf die Bezug genommen wird, ist eine andere Instanz von i
für jede Iteration der Schleife.
Die Funktion existiert bis zu dem von Ihnen angegebenen Intervall. Das ist der Grund, warum jede der 3 Funktionen, die in Ihrer Schleife deklariert sind, den Wert von i
; es wurde im enthaltenden Bereich deklariert und bleibt für die Funktion verfügbar.
Wenn Sie in diesem Kontext let
verwenden, wird bei jeder Iteration eine neue Bindung / ein neuer Bereich erstellt. Wenn Sie ein ähnliches Verhalten in ES5 mit var
erreichen wollen, müssen Sie ein IIFE verwenden:
Tags und Links javascript ecmascript-6