The variable b is not defined in each iteration. Your code is not any different from this:
var funcs = [];
var b;
for (var i = 0; i < 3; i++) {
b = i;
//... etc
}
Your intended behaviour is reached with the let
keyword (ES6). As explained on MDN:
let
allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var
keyword, which defines a variable globally, or locally to an entire function regardless of block scope.
Alternatively, you could define b as a function argument, and then fix it with bind
.
var funcs = [];
var f = function(b) {console.log("My value: " + b);};
for (var i = 0; i < 3; i++) {
funcs[i] = f.bind(null, i);
}
Or, you could define a closure to get the local scope you needed:
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = (function () {
var b = i; // now b is local: to this anonymous function
return function() {console.log("My value: " + b);};
})();
}
And, a small, but better, variant of the above passes i as an argument to the closure, so also there b is local to that closure:
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = (function (b) {
return function() {console.log("My value: " + b);};
})(i);
}
Then even better, define the function (factory) once:
var funcs = [];
var f = function(b) {
return function() {console.log("My value: " + b);};
})(i);
for (var i = 0; i < 3; i++) {
funcs[i] = f(i);
}
But, you will agree the let
syntax is so much more readable.