I was Studying about The Closures in Javascript And and I came across this (typical) example
const arr = [];
for (var i = 0; i < 3; i++) {
arr.push(() => i);
}
arr.forEach((el) => console.log(el()));
or
const arr = [];
let i;
for (i = 0; i < 3; i++) {
arr.push(() => i);
}
arr.forEach((el) => console.log(el()));
that outputs
3
3
3
and I get it, Is because Var doesnt respect scope, and its like defining i with let, out of the scope, example:
let i;
for (i = 0; i < 3; i++) {
// do something
}
so When you Execute the function Inside of The array, and Out of the For Loop, It returns the last value of i
so, I understand Why when i call the function inside of the array, it returns the last Value of i but, that leave me thinking, and I started asking my self, why when I Declare Let i inside the For, and then call the function it returns the values of i of every iteration (0, 1, 2).
My conclusion was that because of the Scope in which it was declared the function Takes i and its value in that exact moment (difficult to explain my self :/), but then I Started to make some Test, and the results where actually very confusing to me.
So, what I did, was to create a Scope and Simulate Loop like that
const arr = [];
// let i = 0;
{
let i = 0;
i++;
arr.push(() => i);
i++;
arr.push(() => i);
i++;
arr.push(() => i);
i++;
arr.push(() => i);
i++;
arr.push(() => i);
}
arr.forEach((el) => console.log(el()));
at first after writting, I Expect that it wouldnt work, because it seems nonsense, but i run it anyway, That was the "expected output"
1
2
3
4
5
But This was the actual Output
5
5
5
5
5
so ok, Then I came To the Conclusion That In Every Iteration of the for Loop It creates a New variable i with the Value increased/decreased (defined for the 3rd part of the for loop), But then I quickly realize that it couldnt be, Because if that were the case, You could define i like a constant
(Now that Im writing this, I see the Stupid I was) so, Then that I Started Thinking more calmly I Came to the conclusion that may be, In every Iteration, The for Loop would create a New Scope, and The function would remember the value of i because it was in his same scope, something Like This :
const arr = [];
{
let i = 0;
{
i++;
arr.push(() => i);
}
{
i++;
arr.push(() => i);
}
{
i++;
arr.push(() => i);
}
{
i++;
arr.push(() => i);
}
{
i++;
arr.push(() => i);
}
}
arr.forEach((el) => console.log(el()));
or this:
const arr = [];
// let i = 0;
{
let i = 0;
if (i < 4) {
i++;
arr.push(() => i);
}
if (i < 4) {
i++;
arr.push(() => i);
}
if (i < 4) {
i++;
arr.push(() => i);
}
if (i < 4) {
i++;
arr.push(() => i);
}
if (i < 4) {
i++;
arr.push(() => i);
}
if (i < 4) {
i++;
arr.push(() => i);
}
}
arr.forEach((el) => console.log(el()));
But nop. It doesnt work. Actually I didnt expect to, but it was the only thing that comes to my head
5
5
5
5
5
So, Im Confusing On How the For Loop Creates/manage the Scope, and How is It Posible that the Function inside the Array can remember the Value of i in that Iteration, and doesnt take the last Value when I executed it. Honestly the only thing that comes to my head is that for Loop has some especial Properties or something like that. Could someOne explain me? And Some explanation Simulating a for Loop would Be Nice. The closures Just make me doubt of everything I know xd
Excuse my bad English.