2010-04-28 10 views
10

Überprüfen Sie den folgenden Ausschnitt aus HTML/Javascript-Code aus:Was ist der Umfang einer JavaScript-Variable, die in einer for() - Schleife deklariert ist?

<html> 
<head> 
<script type="text/javascript"> 
var alerts = []; 
for(var i = 0; i < 3; i++) { 
    alerts.push(function() { document.write(i + ', '); }); 
} 

for (var j = 0; j < 3; j++) { 
    (alerts[j])(); 
} 

for (var i = 0; i < 3; i++) { 
    (alerts[i])(); 
} 
</script> 
</head><body></body></html> 

Diese Ausgänge:

3, 3, 3, 0, 1, 2 

, die nicht das, was ich erwartet hatte - ich 0, 1, 2, 0, 1, 2,

ich die Ausgabe erwartete (fälschlicherweise) angenommen, dass die anonyme Funktion, die in das Array geschoben wird, sich wie eine Schließung verhält und den Wert von i erfasst, der beim Erstellen der Funktion zugewiesen wird - aber es erscheint tatsächlich i verhält sich wie eine globale Variable.

Kann jemand erklären, was in diesem Codebeispiel mit dem Bereich i passiert und warum die anonyme Funktion ihren Wert nicht erfasst?

Antwort

6

In Javasript ist die einzige "interessante" lexikalische Bereichsgrenze der Funktionskörper. Alles, was irgendwo in einer Funktion deklariert ist (also irgendwo anders als eine andere verschachtelte Funktion!), Ist im selben Umfang. Es gibt auch einige seltsame Dinge über die Art, wie die Deklarationen interpretiert werden.

Ihre anonyme Funktion fungiert als eine Schließung, aber jede instanziierte Funktion wird das gleiche "i" teilen. Ein Trick, den ich verwenden ist eine weitere Ebene der Funktion hinzuzufügen:

for (var i = 0; i < whatever; i++) { 
    (function(idaho) { 
    whatever(function() { alert("my own private " + idaho); }); 
    })(i); 
} 

Bei somepoint hoffentlich alle Browser wird die neue „let“ Aussage unterstützen, die eine kürzere, weniger seltsam aussehende Art und Weise im Grunde die gleiche Sache zu tun .

8

Der Bereich ist die Funktion, in der die Variable definiert ist (außer es gibt keinen einzigen, also ist es global).

Die anonyme Funktion, die Sie übergeben, greift auf die Variable zu, die im Gültigkeitsbereich der übergeordneten Funktion (wieder global) definiert ist.

Sie benötigen eine tatsächliche Schließung.

alerts.push(
    function (foo) { 
     return function() { 
      document.write(foo + ', '); 

     } 
    }(i) 
); 
+0

richtige Antwort - danke! - Aber ich habe Pointys Antwort akzeptiert, weil "mein eigener" + Idaho mich zum Lachen gebracht hat ... –