Javascript var Deklaration innerhalb der Schleife

8
%Vor%

Es wird "setting 1" und "setting 2" wie erwartet ausgegeben, aber nach dem Timeout gibt es "test 2" zweimal aus - aus irgendeinem Grund wird die Variable "no" nicht nach der ersten Schleife zurückgesetzt ...

Ich habe nur eine "hässliche" Problemumgehung gefunden:

%Vor%

Haben Sie Ideen, wie Sie dieses Problem direkter umgehen können? oder ist das der einzige Weg?

    
Carlos Ouro 28.04.2010, 15:58
quelle

4 Antworten

13

JavaScript hat keinen Blockbereich, und die Deklarationen von Variablen werden gehisst. Diese Fakten zusammen bedeuten, dass Ihr Code entspricht:

%Vor%

Zu dem Zeitpunkt, zu dem Ihre Timeout-Funktion ausgeführt wird, ist die Schleife lang abgeschlossen, wobei no den endgültigen Wert von 2 beibehält.

Eine Möglichkeit wäre, den aktuellen Wert von no an eine Funktion zu übergeben, die für jeden Aufruf von setTimeout einen neuen Callback erstellt. Jedes Mal, wenn eine neue Funktion erstellt wird, bedeutet dies, dass jeder setTimeout-Callback an einen anderen Ausführungskontext mit einer eigenen Gruppe von Variablen gebunden ist.

%Vor%     
Tim Down 28.04.2010, 16:09
quelle
2

Dies ist im Wesentlichen das Gleiche wie Ihr Fix, aber Sie verwenden eine andere Syntax, um die Bereichsanpassung zu erreichen.

%Vor%     
John Fisher 28.04.2010 16:06
quelle
1

Javascript hat kein lexikalisches Scoping (die for-Schleife erstellt keinen neuen Bereich) und Ihre Lösung ist die Standardumgehung. Eine andere Möglichkeit, dies zu schreiben, könnte sein:

%Vor%

forEach () wurde in ECMAScript 5 eingeführt und ist in modernen Browsern, aber nicht in IE vorhanden. Sie können meine Bibliothek verwenden, um es jedoch zu emulieren.

    
airportyh 28.04.2010 16:07
quelle
1

Ich mag es, dass ich so viele Kilometer aus diese Antwort .

Wenn Sie Hilfe bei der Anwendung dieser Antwort benötigen, lassen Sie es mich wissen.

BEARBEITEN

Sicher. Schauen wir uns Ihren ursprünglichen Code an.

%Vor%

Sehen Sie diese anonyme Funktion? Derjenige, den Sie in setTimeout() übergeben? Es wird nicht aufgerufen, bis der Timer dies sagt - was bei 500ms ist, nachdem die Schleife verlassen hat.

Was Sie erhoffen, ist, dass no "vor Ort" ausgewertet wird, aber nicht - es wird zum Zeitpunkt des Aufrufs der Funktion ausgewertet. Zu diesem Zeitpunkt ist no 2.

Um dies zu umgehen, benötigen wir eine Funktion, die während der Iteration der Schleife ausgeführt wird, die ihrerseits eine Funktion zurückgibt, die setTimeout() so verwenden kann, wie wir es erwarten.

%Vor%

Da wir eine anonyme Funktion erstellen und sie sofort aufrufen, wurde ein neuer Bereich geschaffen, in dem wir Variablen schließen können. Und dieser Bereich schließt sich um value , nicht no . Da value für jede Schleife einen neuen (ähem) Wert erhält, hat jedes dieser Lambdas eine eigene Wert - der, den wir wollen.

Wenn also setTimeout () ausgelöst wird, wird die von unserer Closure-Funktion zurückgegebene Funktion ausgeführt.

Ich hoffe, das erklärt es.

    
Peter Bailey 28.04.2010 16:03
quelle

Tags und Links