3

Here is a canonical sample illustrating the issue with local variables captured by closures:

var a = []
for (var i = 1; i <= 3; i++) {
    a.push(() => i)
}
var v = a.map(f => f())
console.log(v)

The result is [ 4, 4, 4 ], so far so good.

But when qualifying i with let instead of var:

var a = []
for (let i = 1; i <= 3; i++) {
    a.push(() => i)
}
var v = a.map(f => f())
console.log(v)

we get [ 1, 2, 3 ].

I don't understand why: even though let scopes i to the for loop, there is always a single i for all the closures, so this should not changed anything.

And for me the for loop with let should be equivalent to:

var a = []
{ // Scope for the loop
    let i = 1
    do {
        a.push(() => i)
    }
    while (++i <= 3)
}
var v = a.map(f => f())
console.log(v)

like AFAIK it is in C, C++, Java, C#... and which gives [ 4, 4, 4 ].

Obviously I'm wrong, so what am I missing?

Pragmateek
  • 13,174
  • 9
  • 74
  • 108
  • 1
    There is not a single `i` for all the closures, but one `i` for each closure. – Washington Guedes Nov 24 '18 at 19:22
  • The `let` keyword in the `for` loop initialiser doesn't create the variable outside of the loop, it creates a new variable inside the block scope of the loop body in every iteration. – Bergi Nov 24 '18 at 19:42
  • Thanks, indeed the semantics is really different from the other languages I've mentioned, and the compiler handles this case in a special manner if I understand well. – Pragmateek Nov 24 '18 at 20:53

0 Answers0