Reputation: 143
I am interested how for loop operate behind the scenes in ES6.
This is the basic example
var funcs = [];
for (let i = 0; i < 5; i++) {
funcs.push(function () {
console.log(i);
});
};
The reason each function will get proper i value (from 0 to 4) is because let is creating 5 new scopes and functions are bound to their corresponding scope. Thats what I think and that makes most sense to me. If that is the case then it doesnt make sense why const declaration (i) is failing since it should be creating 5 new scopes and const variables can live happily in different scopes. Before let we have do use IIFE in order to achieve the same effect, but what that code did is that it basically created new scopes for the functions and I thought let is doing the same behind the scenes.
If the above statement is not correct, then it must be that let inside for loop is only creating one scope but then I do not get how is that different from var declaration and how functions get proper i value. To make it even more clear, lets say that let is bound to one new scope which is created by the for loop and var declaration is hoisted to the global scope in this case but thats still one scope to be working with.
Can anyone share some light on this topic?
Upvotes: 1
Views: 1506
Reputation: 665584
The reason each function will get proper i value (from 0 to 4) is because let is creating 5 new scopes and functions are bound to their corresponding scope.
Yes, this is what happens. See Explanation of `let` and block scoping with for loops for details (actually there are 6 scopes).
If that is the case then it doesnt make sense why const declaration (i) is failing since it should be creating 5 new scopes and const variables can live happily in different scopes.
Your false assumption here is that const
works the same as let
. Yes, it would totally be possible for 5 const
s to be created in the loop body evaluations. But that just doesn't make sense for a loop like
for (const i=0; i<5; i++) {
console.log(i);
}
which would lead to a TypeError: Assignment to constant variable
- you cannot increment a const
. So you shouldn't use it in a for
loop (notice that for…in
and for…of
loops are different again).
OK, one could write something like
let i=0; for (const j=i; i<5; i++) …
and expect it to work and get 5 different const j
variables in the body. But that's not what happens either, as that's a totally weird way to write this. If you want a const
declaration in each loop iteration, better write it explicitly:
for (let i=0; i<5; i++) {
const j=i;
…
}
which is clean and clear and actually does what you might have expected above.
How const
declarations in for
loops are actually meant to be used can be shown in this example:
for (const iterator = {…}; iterator.hasNext(); iterator.step()) {
… iterator.getValue() …
}
If we check the spec, this actually has the same effect as
{
const iterator = {…};
for (; iterator.hasNext(); iterator.step()) {
… iterator.getValue() …
}
}
which means that the const
ant is declared once in the head of the loop. It doesn't make sense to re-declare it in every iteration, after all its value is constant anyway.
Upvotes: 3