"Var" o no "var" nel ciclo "for-in" di JavaScript?


99

Qual è il modo corretto per scrivere un for-inciclo in JavaScript? Il browser non invia reclami su nessuno dei due approcci che mostro qui. Innanzitutto, esiste questo approccio in cui la variabile di iterazione xviene dichiarata esplicitamente:

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

E in alternativa questo approccio che legge in modo più naturale ma non mi sembra corretto:

for (x in set) {
    ...
}

Proprio imbattuto in questo post quando la risoluzione dei problemi per cui un webpack file generato pacco stava causando errori a un ciclo in cui varnon è stato utilizzato per dichiarare l'iteratore i: Uncaught ReferenceError: i is not defined. Così sarò ad usarlo da ora in poi: / webpack Tratta variabili "globali" Stranamente, per maggiori informazioni, vedere: stackoverflow.com/a/40416826
user1063287

Risposte:


103

Usa var, riduce l'ambito della variabile, altrimenti la variabile cerca fino alla chiusura più vicina alla ricerca di varun'istruzione. Se non riesce a trovare un, varallora è globale (se sei in modalità rigorosa using strict, le variabili globali generano un errore). Questo può portare a problemi come i seguenti.

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

Se scrivi var inel ciclo for, viene visualizzato l'avviso 2.

Scoping e sollevamento JavaScript


4
Non risponde alla domanda, questo è normale per ciclo for, non for in.
IllidanS4 vuole che Monica torni il

Il motivo i == 5 non è dovuto più al sollevamento che alla mancanza di var nel ciclo for?
Snekse

1
Un altro aspetto importante è che la modalità rigorosa proibisce la creazione implicita di proprietà gobal, quindi l'uso del ciclo standard "for in" senza l'istruzione var fallirà e restituirà un ReferenceError.
dkugappi

2
Ma, provenendo da Java, mettere l' varinterno della fortesta sembra che sia locale nel ciclo for, cosa che non è. Quindi, preferisco lo stile di user422039 di seguito.
njlarsson

2
E se ti capita di avere più di un ciclo for in un ambito? Dovrai riutilizzare l'indice (no var), oppure dovrai dichiarare un sacco di nuove variabili (j, k, l, m,…) che non utilizzerai mai più.
armin

40

La prima versione:

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

dichiara una variabile locale chiamata x. La seconda versione:

for (x in set) {
    ...
}

non.

Se xè già una variabile locale (cioè hai a var x;o var x = ...;da qualche parte prima nel tuo ambito corrente (cioè la funzione corrente)) allora saranno equivalenti. Se xnon è già una variabile locale, l'utilizzo della seconda dichiarerà implicitamente una variabile globale x. Considera questo codice:

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();

ci si potrebbe aspettare che questo avviso hey, there, heli, hey, there, copter, ma dal momento che la xè una e la stessa avviserà hey, there, there, hey, there, there. Non lo vuoi! Usa var xnei tuoi forloop.

Per finire: se il forciclo è nello scope globale (cioè non in una funzione), allora lo scope locale (lo scope xè dichiarato in se si usa var x) è lo stesso dello scope globale (lo scope xè implicitamente dichiarato in se usi xsenza var), quindi le due versioni saranno identiche.


3
Finalmente una risposta completa con spiegazione e bell'esempio. E risponde davvero alla domanda.
IllidanS4 vuole che Monica torni il

22

Dovresti davvero dichiarare le variabili locali con var, sempre .

Inoltre, non dovresti usare i cicli "for ... in" a meno che tu non sia assolutamente sicuro che sia quello che vuoi fare. Per iterare attraverso array reali (che è abbastanza comune), dovresti sempre usare un ciclo con un indice numerico:

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

Iterare attraverso un semplice array con "for ... in" può avere conseguenze inaspettate, perché il tuo ciclo potrebbe raccogliere attributi dell'array oltre a quelli numerici.

modifica - qui nel 2015 va bene anche da usare .forEach()per iterare attraverso un array:

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
  ...
});

Il .forEach()metodo è presente sul prototipo Array da IE9 in avanti.


12

In realtà, se non ti piace la dichiarazione all'interno fordell'intestazione, puoi fare:

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

Come accennato in altre risposte a questa domanda, non utilizzare varaffatto produce effetti collaterali non necessari come l'assegnazione di una proprietà globale.


9

Usa quello in cui dichiari la variabile di ciclo con var. Le variabili dichiarate implicitamente hanno un ambito diverso che probabilmente non è quello che intendevi.


9
for(var i = 0; ...)

è un pattern comunemente visto ma è diverso da

for(int i; ...)

in C ++ in quanto la variabile non è limitata al forblocco. Infatti, varviene sollevato in cima all'ambito (funzione) che lo racchiude in modo che un locale isia effettivamente disponibile sia prima chefor ciclo (dopo l'inizio dell'ambito / funzione corrente) che dopo di esso.

In altre parole, facendo:

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

equivale a:

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

ES6 ha la letparola chiave (invece di var) per limitare l'ambito al blocco for.

Ovviamente, DOVREBBE usare variabili locali (quelle dichiarate con varo leto const(in ES6)) piuttosto che globali implicite.

for(i=0; ...)o for(i in ...)fallirà se usi "use strict";(come dovresti) e inon viene dichiarato.



4

Penso che var sia buono per motivi di prestazioni.

Javascript non esaminerà l'intero ambito globale per vedere se x esiste già da qualche altra parte.


3

Da un punto di vista generale, la prima versione sarà per un indice che deve risiedere all'interno dell'ambito del ciclo, mentre l'altra sarebbe una qualsiasi variabile nell'ambito in cui è stato richiamato il costruttore del ciclo.

Se hai intenzione di utilizzare l'indice del ciclo all'interno del ciclo for e questo non sarà richiesto da altri nelle righe successive, è meglio dichiarare la variabile con "var" così sarai sicuro che "x" sia l'indice del ciclo inizializzato con 0, mentre l'altra, se un'altra variabile "x" è disponibile in questo contesto, questa verrà sovrascritta dall'indice del ciclo - quindi avrai degli errori logici -.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.