It's the good-old i
+ scope issue again ;)... the solution:
function init(list)
{
var item, result = [];
for (var i = 0; i<list.length; i++)
{
item = 'item' + list[i];
result.push((function(val, idx)
{//create this function with its own scope
return function()
{//return this function, which has access to val and idx
alert(val+' '+list[idx]);
};
}(i, item));//pass vals of i and item to function, and call it here (IIFE)
}
return result;
}
Why? all functions created in a given scope, have access to any variable declared in that higher scope. So the functions you're pushing into result
have, indeed access to i
, item
and list
. They have access, but don't own their own copy of those variables.
on each iteration of the for loop, i is incremented, so it's 0, 1, 2,3. When its value hits 3, the it's value is no longer < list.length
so the loop ends. But inside the functions you're creating list[i]
evaluates to list[3]
, which is undefined.
The same applies to item
, the variable is declared in the init
function, where it's reassigned on each iteration, too, hence whichever of the created functions you call, they will reference whatever was last assigned to item
: "item3" in your case.
I've posted a fairly lengthy answer that explains this in detail, and I've added a lot of info to the tag-wiki, too. For now, you can easily test this like so:
function init(list)
{
var j, result = [];
for (var i = 0; i<list.length; i++)
{
var item = 'item' + list[i];
result.push( function() { alert( item + ' ' +list[i] ) } );
for (j=0;j<=i;j++)
{
result[j]();
}
}
alert(i);
return result;
}
This will alert something like:
//i = 0
item1 1
//i = 1
item2 1
item2 2
//i=2
item3 1
item3 2
item3 3
//outside loops, alert i:
3