The difference in behavior between let and var in the for loop

The difference in declaring a loop counter via let and var is that via var the counter variable is visible outside the loop in the function, while via let it is visible only within the loop. Please explain why there are different conclusions in these cases

for(var i = 0; i < 10; i++) setTimeout(() => console.log(i), 1000)

Here we get ten tens.

for(let i = 0; i < 10; i++) setTimeout(() => console.log(i), 1000)

And here from zero to ten.

With the first example, everything is clear, but why is it so in the second? i after all, it is created once and scrolls until the first setInterval is executed. dozens. In a word-why do these two examples have different results?

Author: torokhkun, 2017-09-09

2 answers

Https://learn.javascript.ru/let-const

When used in a loop, a different variable is created for each iteration.
The var variable is one for all iterations of the loop and is visible even after the loop.
With the let variable, everything is different.
Each repetition of the loop corresponds to its own independent variable let. If there are nested function declarations inside the loop, then the closure of each one will contain the variable that was present during the corresponding iteration.

 8
Author: Gleb Kemarsky, 2017-09-09 08:34:29

It's all about the scope of the variable. The let statement declares a variable that is confined to the block scope. What is a block scope? Here is an example

let a = 10;

{
   let a = 20;
   console.log(a); // 20
}

console.log(a); // 10

As you can see inside the block and outside it, ES6 creates completely different variables. The variable created by the let statement is visible only in its scope and cannot be accessed outside of its scope.

Here's what happens if you try the same thing with the operator var.

var a = 10;

{
   var a = 20;
   console.log(a); // 20
}

console.log(a); // 20

As you can see, the var operator does not fully comply with the block visibility rules.

Can your example be simplified for greater clarity

for(let i = 0; i < 10; i++) setTimeout(() => console.log(i), 1000)

1) Can be represented as follows

for(let i = 0; i < 10; i++){
    setTimeout(
       function(){console.log(i);}, 
          1000
    )
}

2) And split into lines

{
    let i = 0;
    setTimeout(
        function(){console.log(i);},
        1000
    )
}

{
    let i = 1;
    setTimeout(
        function(){console.log(i);},
        1000
    )
}

{
    let i = 2;
    setTimeout(
        function(){console.log(i);},
        1000
    )
}
/** И так 10 раз .... 
    После 1000 миллисекунд запуститься наша тайемр-функция, и 
    поскольку в каждом блоке благодаря оператору let создавалась свая 
    переменная то в таймер-функиции будет та переменная которая была 
    создана в том же блоке.**/

But with the var operator, everything is different.

{
    var i = 0;
    setTimeout(
        function(){console.log(i);},
        1000
    )
}

{
    var i = 1;
    setTimeout(
        function(){console.log(i);},
        1000
    )
}

{
    var i = 2;
    setTimeout(
        function(){console.log(i);},
        1000
    )
}
/** И так 10 раз ...
    Поскольку во всех блоках будет одна и та же 
    переменная то после того как через 1000 миллисекунд запущенная 
    таймер-функция прочитает последнее значение переменной i - которое 
    у нас будет 10.**/

Somehow this is how things are with javascript. You can read more about the block scope here and here.

 4
Author: Daniel Abyan, 2017-09-15 11:29:55