es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Comportamiento de las variables let declaradas dentro de un bucle for en el contexto de los closures.

En el siguiente fragmento de código, la función pasada a setTimeout forma un cierre con la variable i, la cual está presente en el alcance del script. Por lo tanto, la función contiene una “referencia” a la variable i. El valor de i se actualiza a 5 antes de que se registre en la consola. Y la salida es: 5 5 5 5 5 (con saltos de línea).

script.js:

let i;
for (i = 0; i < 5; ++i) {
    setTimeout(() => {
        console.log(i);
    }, i * 1000);
}

La parte anterior me queda clara. Pero cuando declaro la variable i “dentro” del bucle for, entonces i tiene un alcance de bloque limitado al bucle for.

for (let i = 0; i < 5; ++i) {
    setTimeout(() => {
        console.log(i);
    }, i * 1000);
}

En este fragmento de código, espero que la salida sea la misma que en el primer fragmento, porque el cierre contiene una “referencia” a la variable i y el valor de esa “referencia” debería actualizarse a 5 antes de que se registre en la consola. Pero la salida real es: 0 1 2 3 4 (con saltos de línea).

La pregunta es, ¿por qué el código del segundo fragmento se comporta de esta manera?

¿Es porque:
1. Se crea una nueva copia de la variable i en la memoria para cada iteración del bucle for y la copia anterior se recoge como basura? No estoy seguro de cómo funciona la gestión de memoria en los bucles.
2. En lugar de almacenar una referencia de i, ¿se almacena el “valor” de i en el cierre? No creo que sea el caso.
3. ¿Algo más?

Por favor, ayúdame a aclarar esto. ¡Gracias!

Tags:  ,

Answer

  1. Avatar for davy.ai

    La razón por la que el código en el segundo fragmento se comporta de manera diferente es porque cuando se usa let para declarar i dentro del bucle for, i tiene un alcance de bloque solo para el bucle for. Esto significa que cada iteración del bucle tiene su propia instancia separada de i. Cuando se llama a la función setTimeout en cada iteración, crea un cierre alrededor de la instancia de i para esa iteración en particular, y no la variable i en el ámbito exterior. Por lo tanto, cada llamada a la función registra el valor de la instancia separada de i que se creó para esa iteración del bucle, lo que resulta en la salida 0 1 2 3 4.

    En resumen, la diferencia en el comportamiento de los dos fragmentos de código se debe a las reglas de alcance de let y la creación de una instancia separada de i para cada iteración del bucle.

Comments are closed.