Estoy tratando de entender este código.

let a = [1, 2, 3, 4, 5];

a.forEach(i => {
  setTimeout(i => {
    console.log(i);
  }, 1000);
});

Por qué está dando salida algo como esto:

5 times: undefined

Sé que javascript ejecuta el código de forma asincrónica y programa la función setTimeout, cuando se detiene la iteración, el último valor de i no está definido, pero por qué no está definido.
¿En javascript no podemos acceder al alcance del parámetro de devolución de llamada externa?

1
Ven Nilson 10 may. 2019 a las 18:18

4 respuestas

La mejor respuesta

Eso es solo sombra estándar.

Considere el siguiente código:

let x = "outer";
console.log(x);
{
    let x = "inner";
    console.log(x);
}
console.log(x);

El bloque interno no puede acceder al x externo porque ha declarado una variable local con el mismo nombre.

Del mismo modo, en su código hay dos variables llamadas i:

    a.forEach(i => {
        setTimeout(i => {

La única diferencia es que son parámetros de función, no declarados con let. Aparte de eso, funcionan de la misma manera: el i interno sombrea el i externo, evitando el acceso. Para solucionar esto, simplemente quite el i interno. setTimeout no pasa ningún argumento útil a la devolución de llamada de todos modos.

3
melpomene 10 may. 2019 a las 15:23

Otra opción es utilizar el tercer parámetro para setTimeout. Todos los parámetros agregados después de delay se pasarán como parámetros a la función dentro de setTimeout

Esta es la sintaxis:

setTimeout(func[, delay, param1, param2, ...])

Aquí, param1, param2 etc. se pasan como parámetros a func

let a = [1, 2, 3, 4, 5];
a.forEach(i => {
  setTimeout(value => {
    console.log(value);
  }, 1000, i);
});

Esto es útil si tiene la función definida por separado y no puede cerrar la llamada i de forEach

function callback(value) {
  console.log(value)
}

let a = [1, 2, 3, 4, 5];
a.forEach(i => {
  setTimeout(callback, 1000, i);
});
3
adiga 10 may. 2019 a las 15:34

Su devolución de llamada interna tiene un parámetro llamado i, que sombrea el i externo.

setTimeout() no pasa ningún parámetro a su devolución de llamada, por lo que el i interno es undefined.

Para usar un parámetro o variable de la devolución de llamada externa, simplemente utilícelo.

3
SLaks 10 may. 2019 a las 15:20

Simplemente elimine el i en setTimeout

let a = [1,2,3,4,5];
a.forEach((i) => {
    setTimeout(() => {
        console.log(i);
    }, 1000);
});
4
Cid 10 may. 2019 a las 15:22