"Var" oder kein "var" in der "for-in" -Schleife von JavaScript?

99

Was ist der richtige Weg, um eine for-inSchleife in JavaScript zu schreiben ? Der Browser beschwert sich nicht über einen der beiden hier gezeigten Ansätze. Erstens gibt es diesen Ansatz, bei dem die Iterationsvariable xexplizit deklariert wird:

for (var x in set) {
    ...
}

Und alternativ dieser Ansatz, der natürlicher liest, mir aber nicht richtig erscheint:

for (x in set) {
    ...
}
Futlib
quelle
Ich bin gerade auf diesen Beitrag gestoßen, als ich Fehler behoben habe, warum eine vom Webpack generierte Bundle-Datei Fehler in einer for-Schleife verursachte, in varder der Iterator nicht deklariert wurde i: Uncaught ReferenceError: i is not defined. Also werde ich es von nun an verwenden: / webpack behandelt "globale" Variablen seltsam, für weitere Informationen
user1063287

Antworten:

103

Verwenden varSie diese Option, um den Umfang der Variablen zu verringern. Andernfalls sucht die Variable bis zum nächsten Abschluss und sucht nach einer varAnweisung. Wenn es a nicht finden kann, varist es global (wenn Sie sich in einem strengen Modus befinden, using strictwerfen globale Variablen einen Fehler auf). Dies kann zu Problemen wie den folgenden führen.

function f (){
    for (i=0; i<5; i++);
}
var i = 2;
f ();
alert (i); //i == 5. i should be 2

Wenn Sie var iin die for-Schleife schreiben, wird die Warnung angezeigt 2.

JavaScript Scoping und Hoisting

Gabriel Llamas
quelle
4
Beantwortet die Frage nicht, dies ist für normale for-Schleife, nicht für in.
IllidanS4 will Monica
Liegt der Grund i == 5 nicht mehr am Heben als am Fehlen von var in der for-Schleife?
Snekse
1
Ein weiterer wichtiger Aspekt dabei ist, dass der strikte Modus die implizite Erstellung globaler Eigenschaften verbietet. Daher schlägt die Verwendung der Standardschleife "for in" ohne die var-Anweisung tatsächlich fehl und gibt einen ReferenceError zurück.
dkugappi
2
Aber, aus Java, die Umsetzung varin den forBlicken Kopf wie es für Schleife in der lokalen ist, was es nicht ist. Daher bevorzuge ich den folgenden Stil von user422039.
Njlarsson
2
Was ist, wenn Sie mehr als eine for-Schleife in einem Bereich haben? Sie müssen entweder den Index (no var) wiederverwenden oder viele, viele neue Variablen (j, k, l, m, ...) deklarieren, die Sie nie wieder verwenden werden.
Armin
40

Die erste Version:

for (var x in set) {
    ...
}

deklariert eine lokale Variable namens x. Die zweite Version:

for (x in set) {
    ...
}

nicht.

Wenn xes sich bereits um eine lokale Variable handelt (dh Sie haben eine var x;oder eine var x = ...;frühere Variable in Ihrem aktuellen Bereich (dh die aktuelle Funktion)), sind diese gleichwertig. Wennx es sich nicht bereits um eine lokale Variable handelt, wird bei Verwendung der zweiten implizit eine globale Variable deklariert x. Betrachten Sie diesen Code:

var obj1 = {hey: 10, there: 15};
var obj2 = {heli: 99, copter: 10};
function loop1() {
    for (x in obj1) alert(x);
}
function loop2() {
    for (x in obj2) {
        loop1(); 
        alert(x);
    }
}
loop2();

Sie könnte dies zu Alarm erwarten hey, there, heli, hey, there, copter, aber da das xist ein und dasselbe es alarmiert hey, there, there, hey, there, there. Das willst du nicht! Verwenden Sie var xin Ihren forSchleifen.

Um das Ganze abzurunden: Wenn sich die forSchleife im globalen Bereich befindet (dh nicht in einer Funktion), entspricht der lokale Bereich (der Bereich xwird bei Verwendung deklariert var x) dem globalen Bereich (der Bereich xwird implizit in deklariert) Wenn Sie xohne var) verwenden, sind die beiden Versionen identisch.

Claudiu
quelle
3
Endlich eine vollständige Antwort mit Erklärung und schönem Beispiel. Und es beantwortet wirklich die Frage.
IllidanS4 will Monica
22

Sie sollten sich wirklich lokale Variablen mit erklären var, immer .

Sie sollten auch keine "for ... in" -Schleifen verwenden, es sei denn, Sie sind sich absolut sicher, dass Sie dies tun möchten. Zum Durchlaufen realer Arrays (was ziemlich häufig vorkommt) sollten Sie immer eine Schleife mit einem numerischen Index verwenden:

for (var i = 0; i < array.length; ++i) {
  var element = array[i];
  // ...
}

Das Durchlaufen eines einfachen Arrays mit "for ... in" kann unerwartete Konsequenzen haben, da Ihre Schleife möglicherweise neben den numerisch indizierten auch Attribute des Arrays aufnimmt.

edit - hier im Jahr 2015 ist es auch in Ordnung, .forEach()ein Array zu durchlaufen:

array.forEach(function(arrayElement, index, array) {
  // first parameter is an element of the array
  // second parameter is the index of the element in the array
  // third parameter is the array itself
  ...
});

Die .forEach()Methode ist auf dem Array-Prototyp ab IE9 vorhanden.

Spitze
quelle
12

Wenn Sie eine Erklärung innerhalb der forÜberschrift nicht mögen , können Sie Folgendes tun:

var x;
for (x in set) {
    ...
}

Wie in anderen Antworten auf diese Frage erwähnt, führt die varNichtverwendung zu unnötigen Nebenwirkungen wie der Zuweisung einer globalen Eigenschaft.

user422039
quelle
9

Verwenden Sie diejenige, mit der Sie die Schleifenvariable deklarieren var. Implizit deklarierte Variablen haben einen anderen Bereich, der wahrscheinlich nicht Ihren Vorstellungen entspricht.

Joel Coehoorn
quelle
9
for(var i = 0; ...)

ist ein häufig gesehenes Muster, aber es unterscheidet sich von

for(int i; ...)

in C ++ dahingehend, dass die Variable nicht auf den forBlock beschränkt ist. Tatsächlich wird der varan die Spitze des umschließenden Bereichs (Funktion) gehisst, so dass ein lokaler isowohl vor demfor Schleife (nach dem Beginn des aktuellen Bereichs / der aktuellen Funktion) .

Mit anderen Worten:

(function(){ //beginning of your current scope;
 //...
 for(var i in obj) { ... };
})();

ist das gleiche wie:

(function(){ //beginning of your current scope;
 var i;
 //...
 for(i in obj) { ... };
})();

ES6 hat das letSchlüsselwort (anstelle von var), um den Bereich auf den for-Block zu beschränken.

Natürlich sollten Sie lokale Variablen (solche, die entweder mit varoder letoder const(in ES6) deklariert sind ) anstelle impliziter Globals verwenden.

for(i=0; ...)oder for(i in ...)schlägt fehl, wenn Sie "use strict";(wie Sie sollten) verwenden und inicht deklariert sind.

PSkocik
quelle
4

Ich denke, var ist aus Leistungsgründen gut.

Javascript durchsucht nicht den gesamten globalen Bereich, um festzustellen, ob x bereits an einer anderen Stelle vorhanden ist.

neebz
quelle
3

Aus allgemeiner Sicht bezieht sich die erste Version auf einen Index, der im Bereich der Schleife liegen muss, während die andere eine beliebige Variable im Bereich ist, in der der Konstruktor der Schleife aufgerufen wurde.

Wenn Sie den Index der Schleife in for loop verwenden möchten und dies in den nächsten Zeilen von anderen nicht benötigt wird, deklarieren Sie die Variable besser mit "var", damit Sie sicher sind, dass "x" für den mit 0 initialisierten Index der Schleife steht. Während die andere, wenn in diesem Kontext eine andere "x" -Variable verfügbar ist, diese vom Index der Schleife überschrieben wird - das sind einige logische Fehler -.

Matías Fidemraizer
quelle