es6 entre ecmascript diferencias diferencia javascript for-loop scope const ecmascript-6

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

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-in-and-for-of-statements-static-semantics-boundnames

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.

http://www.ecma-international.org/ecma-262/6.0/index.html#sec-for-statement-runtime-semantics-labelledevaluation


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.