¿"Var" o no "var" en el bucle "for-in" de JavaScript?

99

¿Cuál es la forma correcta de escribir un for-inbucle en JavaScript? El navegador no emite una queja sobre ninguno de los dos enfoques que muestro aquí. Primero, existe este enfoque donde la variable de iteración xse declara explícitamente:

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

Y, alternativamente, este enfoque que se lee de forma más natural pero no me parece correcto:

for (x in set) {
    ...
}
futlib
fuente
Sólo encontré con este aviso para solucionar problemas de por qué un webpack generada archivo de paquete estaba causando errores en un bucle donde varno se utiliza para declarar el iterador i: Uncaught ReferenceError: i is not defined. Así que lo usaré de ahora en adelante: / webpack trata las variables "globales" de manera extraña, para obtener más información, consulte: stackoverflow.com/a/40416826
user1063287

Respuestas:

103

Use var, reduce el alcance de la variable, de lo contrario, la variable busca el cierre más cercano buscando una vardeclaración. Si no puede encontrar un, varentonces es global (si está en un modo estricto using strict, las variables globales arrojan un error). Esto puede provocar problemas como los siguientes.

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

Si escribe var ien el bucle for, se muestra la alerta 2.

Elevación y alcance de JavaScript

Gabriel Llamas
fuente
4
No responde la pregunta, esto es para bucle for normal, no for in.
IllidanS4 quiere que Monica regrese el
¿No es la razón por la que i == 5 se debe más al izado que a la falta de var en el bucle for?
Snekse
1
Otro aspecto importante de esto es que el modo estricto prohíbe la creación implícita de propiedades globales, por lo que el uso del bucle estándar "for in" sin la instrucción var fallará y devolverá un ReferenceError.
dkugappi
2
Pero, viniendo de Java, poner el varinterior de la forcabeza parece que es local en el ciclo for, que no lo es. Por lo tanto, prefiero el estilo de user422039 a continuación.
njlarsson
2
¿Qué sucede si tiene más de un bucle for en un alcance? Tendrá que reutilizar el índice (sin var) o tendrá que declarar montones y montones de variables nuevas (j, k, l, m,…) que nunca volverá a utilizar.
armin
40

La primera versión:

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

declara una variable local llamada x. La segunda versión:

for (x in set) {
    ...
}

no.

Si xya es una variable local (es decir, tiene una var x;o en var x = ...;algún lugar anterior en su alcance actual (es decir, la función actual)) entonces serán equivalentes. Si aún xno es una variable local, entonces el uso de la segunda declarará implícitamente una variable global x. Considere este código:

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

se podría esperar que esto alerta hey, there, heli, hey, there, copter, pero ya que el xes uno y el mismo se alertará hey, there, there, hey, there, there. ¡No quieres eso! Úselo var xen sus forbucles.

Para colmo: si el forbucle está en el alcance global (es decir, no en una función), entonces el alcance local (el alcance xse declara en si lo usa var x) es el mismo que el alcance global (el alcance xse declara implícitamente en si lo usa xsin una var), entonces las dos versiones serán idénticas.

Claudiu
fuente
3
Finalmente una respuesta completa con explicación y buen ejemplo. Y realmente responde a la pregunta.
IllidanS4 quiere que Monica vuelva el
22

Realmente debería declarar variables locales con var, siempre .

Tampoco debería utilizar bucles "for ... in" a menos que esté absolutamente seguro de que eso es lo que quiere hacer. Para iterar a través de matrices reales (que es bastante común), siempre debe usar un bucle con un índice numérico:

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

Iterar a través de una matriz simple con "for ... in" puede tener consecuencias inesperadas, porque su ciclo puede recoger atributos de la matriz además de los indexados numéricamente.

editar - aquí en 2015 también está bien usarlo .forEach()para iterar a través de una matriz:

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

El .forEach()método está presente en el prototipo Array desde IE9 en adelante.

Puntiagudo
fuente
12

En realidad, si no le gusta la declaración dentro del forencabezado, puede hacer:

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

Como se mencionó en otras respuestas a esta pregunta, no usar varen absoluto produce efectos secundarios innecesarios, como asignar una propiedad global.

user422039
fuente
9

Use el que declara la variable de ciclo con var. Las variables declaradas implícitamente tienen un alcance diferente que probablemente no sea el que pretendía.

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

es un patrón que se ve comúnmente, pero es diferente de

for(int i; ...)

en C ++ en el sentido de que la variable no tiene el alcance del forbloque. De hecho, varse eleva a la parte superior del alcance (función) adjunto, por lo que un local iestará disponible de manera efectiva tanto antes del forciclo (después del comienzo del alcance / función actual) como después de él.

En otras palabras, haciendo:

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

es lo mismo que:

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

ES6 tiene la letpalabra clave (en lugar de var) para limitar el alcance al bloque for.

Por supuesto, DEBERÍA utilizar variables locales (las declaradas con varo leto const(en ES6)) en lugar de globales implícitas.

for(i=0; ...)o for(i in ...)fallará si usa "use strict";(como debería) y ino se declara.

PSkocik
fuente
4

Creo que var es bueno por razones de rendimiento.

Javascript no examinará todo el alcance global para ver si x ya existe en algún otro lugar.

neebz
fuente
3

Desde un punto de vista general, la primera versión será para un índice que debe vivir dentro del alcance del bucle, mientras que la otra sería cualquier variable en el alcance donde se invocó el constructor del bucle.

Si va a usar el índice del bucle dentro del bucle for y esto no será requerido por otros en las siguientes líneas, mejor declare la variable con "var" para asegurarse de que "x" es el índice del bucle for inicializado con 0, mientras que el otro, si hay otra variable "x" disponible en este contexto, se sobrescribirá con el índice del bucle, es decir, tendrá algunos errores lógicos.

Matías Fidemraizer
fuente