A closure has an enduring reference to the variables it closes over, not a copy of their value as of when it was created. That's why all of your functions see 6
: That's the value that i
has as of when those functions are called.
If you need them to see different values, make the closures close over something else that doesn't change. Here's one way:
function createFunctions(n) {
var callbacks = [];
for (var i=0; i<n; i++) {
callbacks.push(makeCallback(i));
}
return callbacks;
function makeCallback(index) {
return function() {
return index;
};
}
}
Or:
function createFunctions(n) {
var callbacks = [];
for (var i=0; i<n; i++) {
callbacks.push(makeCallback(i));
}
return callbacks;
}
function makeCallback(index) {
return function() {
return index;
};
}
(In this example, it doesn't matter whether makeCallback
is within createFunctions
or outside it.)
Now, the callbacks close over the context containing the index
argument. They each get their own copy of that context (which is created by calling the makeCallback
function), and so since nothing ever changes index
, its value remains unchanged.
More (on my blog): Closures are not complicated
This feature of closures closing over the context of the variable is very, very useful. Consider:
function allocator(start) {
return function() {
return ++start;
};
}
var f = allocator(0);
alert(f()); // "1"
alert(f()); // "2"
alert(f()); // "3"
That wouldn't work if the function created by allocator
had a copy of the value of start
. It works because the function created by allocator
has a reference (through the context) to the variable itself.