The second method is a little clearer if you use a parameter name that does not mask the loop variable name:
funArr[funArr.length] = (function(val) { return function(){ return val; }})(i);
The problem with your current code is that each function is a closure and they all reference the same variable i
. When each function is run, it returns the value of i
at the time the function is run (which will be one more than the limit value for the loop).
A clearer way would be to write a separate function that returns the closure that you want:
var numArr = [];
var funArr = [];
for(var i = 0; i < 10; ++i){
numArr[numArr.length] = i;
funArr[funArr.length] = getFun(i);
}
function getFun(val) {
return function() { return val; };
}
Note that this is doing basically the same thing as the first line of code in my answer: calling a function that returns a function and passing the value of i
as a parameter. It’s main advantage is clarity.
EDIT: Now that EcmaScript 6 is supported almost everywhere (sorry, IE users), you can get by with a simpler approach—use the let
keyword instead of var
for the loop variable:
var numArr = [];
var funArr = [];
for(let i = 0; i < 10; ++i){
numArr[numArr.length] = i;
funArr[funArr.length] = function(){ return i; };
}
With that little change, each funArr
element is a closure bound do a different i
object on each loop iteration. For more info on let
, see this Mozilla Hacks post from 2015. (If you’re targeting environments that don’t support let
, stick with what I wrote earlier, or run this last through a transpiler before using.