When I executed this code I expected to see 100 written in the console 10 times (based on experience from using other languages):
const arr = [];
for (let i = 0; i < 10; i++)
arr.push(() => i * i);
arr.forEach(f => console.log(f()));
But I get the square of each number (from 0 to 9). This seems to behave differently to some other languages.
For instance using C#, you will get 100 ten times:
var list = new List<Func<int>>();
for(var i = 0; i < 10; i++)
list.Add(() => i * i);
list.ForEach(f => Console.WriteLine(f()));
Python prints 81 ten times:
arr = []
for i in range(10):
arr.append(lambda: i * i)
for f in arr:
print(f())
Java doesn't allow this, as captured variables cannot mutate.
See this for examples in other languages.
As Mark explained below, when we use let (block scope) in JavaScript, the value of i is captured in a new scoped variable within each anonymous function. When you look at the actual definition of each function (using : arr.forEach(f => console.dir(f)); ), you'll see that there is a scope (_loop) from which i's value is captured in every iteration:
[[Scopes]]: Scopes[3]
0: Closure (_loop) {i: 0}
[[Scopes]]: Scopes[3]
0: Closure (_loop) {i: 1}
and so on...
If we re-run this example using var, unsurprisingly, the _loop block-level scope is missing and i is saved in the module/file level scope instead with the same value (10) for each iteration:
[[Scopes]]: Scopes[2]
0: Closure (./src/index.js) {i: 10}