I know the outcome of this is 10:
var es = [];
for (var i = 0; i < 10; i++) {
es[i] = function () {
console.log(i);
};
}
es[6]();
Any number of es[0] - es[9] is still 10. but why?
I know the outcome of this is 10:
var es = [];
for (var i = 0; i < 10; i++) {
es[i] = function () {
console.log(i);
};
}
es[6]();
Any number of es[0] - es[9] is still 10. but why?
Because after the loop i
is 10
. The function prints the reference of i
.
There is only integer object created. Those console.log(i)
are all referring to the same object in memory. The value of i
- the only i
- is of course 10 at the end of the loop.
Note the line console.log(i)
creates a closure, which in particular means it's not creating a new reference to the variable referred to by i
. It's the same reference.
A good way to do this analysis is to keep tracking of the number of times in your code a new actual variable is created. If you've programmed in C or C++ or wherever, you know that an integer takes 4 or 8 bytes of memory. The line for(var i = 0;
can be thought of as creating one object. Just one. Nothing inside of the function creates another object, since closures don't do that.
That's because by the time you execute console.log(i)
, i
has changed as the loop finished.
More precisely, the for
loop stops when the condition i < 10
is false, that is when i
is 10
. What you have after that is 10 identical functions, all using the same, externally defined variable i
.
You can fix it using this classical closure trick :
var es = [];
for (var i = 0; i < 10; i++) {
(function(j){
es[j] = function () {
console.log(j);
};
})(i);
}
es[6]();
What this code does is create a new variable, j
, whose scope is the anonymous function call. This is a way to save the value i
has when the function is called (that is during the loop instead of when es[6]
is called).
Because you are referring to i
and after the loop it is 10
i.e, when you are executing console.log(i). The value of i has changed to 10.