javascript - entre - ECMAScript 2015: const en for loops
let javascript (3)
¿Cuál de los dos (o ninguno / ambos) fragmentos de código a continuación debería funcionar en una implementación completa de ECMAScript 2015:
for (const e of a)
for (const i = 0; i < a.length; i += 1)
Según tengo entendido, el primer ejemplo debería funcionar porque
e
se inicializa para cada iteración.
¿No debería ser este el caso para
i
en la segunda versión?
Estoy confundido porque las implementaciones existentes (Babel, IE, Firefox, Chrome, ESLint) no parecen ser consistentes y tienen una implementación completa de
const
, con varios comportamientos de las dos variantes de bucle;
Tampoco puedo encontrar un punto concreto en el estándar, por lo que sería muy apreciado.
El siguiente for-of loop funciona:
for (const e of a)
La especificación ES6 describe esto como:
ForDeclaration: LetOrConst ForBinding
El imperativo para el bucle no funcionará:
for (const i = 0; i < a.length; i += 1)
Esto se debe a que la declaración solo se evalúa una vez antes de ejecutar el cuerpo del bucle.
Esta vez no citaré las especificaciones, porque creo que es más fácil entender lo que sucede con el ejemplo.
for (const e of a) …
Es básicamente equivalente a
{
const __it = a[Symbol.iterator]();
let __res;
while ((__res = __it.next()) && !__res.done) {
const e = __res.value;
…
}
}
Por simplicidad, ignoré que hay una TDZ con
e
para la expresión a, y las diversas
__it.return()
/
__it.throw(e)
en caso de que el bucle salga prematuramente (se
break
o
throw
al cuerpo).
for (const i = 0; i < a.length; i += 1) …
es básicamente equivalente a
{
const i = 0;
while (i < a.length) {
…
i += 1;
}
}
A diferencia de
let
, una declaración
const
en un bucle
for
no se redeclara en cada iteración del bucle (y el inicializador no se vuelve a ejecutar de todos modos).
A menos que
break
en la primera iteración, su
i +=
se lanzará aquí.
Su segundo ejemplo definitivamente no debería funcionar porque
i
se declara una vez y no en cada iteración, esto es solo una función de cómo funciona esa categoría de bucles.
Puedes probar esto en un navegador normal:
for (var i = 0, otherVar = ""; i < [1,2,3,4].length; i += 1){
console.log(otherVar)
otherVar = "If otherVar was initialized on each iteration, then you would never read me.";
}
No es el caso de que
const
esté totalmente prohibido
for
bucles.
Solo
for
eso modificaremos const es.
Estos son validos:
for(const i = 0;;){ break }
for(const i = 0; i < 10;){ break; }
Estos no son válidos:
for(const i = 0;;){ ++i; break; }
for(const i = 0;;++i){ if(i > 0) break; }
No estoy seguro de por qué Firefox da un SyntaxError después de leer la especificación ES2015 (aunque estoy seguro de que las personas inteligentes en Mozilla son correctas), parece que se supone que debe generar una excepción:
Cree un enlace inmutable nuevo pero no inicializado en un Registro de entorno. El valor de cadena N es el texto del nombre enlazado. Si S es verdadero, los intentos de acceder al valor del enlace antes de que se inicialice o establecerlo después de que se haya inicializado siempre generarán una excepción, independientemente de la configuración del modo estricto de las operaciones que hacen referencia a ese enlace. S es un parámetro opcional que por defecto es falso.