Reputation: 892
Learning JavaScript and can't figure out why these two functions are different. I saw this example (I added names to the functions):
var txt = ["a", "b", "c"];
for (var i = 0; i < 3; ++i ) {
setTimeout((function (msg) {
return function () { console.log(msg); }
})(txt[i]), 100);
}
I see that a function that calls console.log
is being returned. So I thought, why not just return it directly:
var txt = ["a", "b", "c"];
for (var i = 0; i < 3; ++i ) {
setTimeout(function() { console.log(txt[i]); }, 100);
}
This ends up showing 'undefined.' I understand that it's because it's trying to access txt[3]
because after one second the loop has finished and i
has been set to 3, but I don't understand how the original setup avoided this problem.
Upvotes: 0
Views: 105
Reputation: 16706
Example 1
The closures execute the script instantly and also allow you to pass a parameter inside which is stored and remains stored inside that function. parameter==param
(function(param){})(parameter)
In your example the function returns another function which will be executed by setTimeout.
(function(param){
return function(){
alert(param)
}
})(parameter)
And as you passed the parameter previously to the function it will return the right value.
Example 2
The setTimeout is called 3 times very fast but the parameter is not stored anywhere so it takes the last value know from txt & i and as the loop is ended before the setTimeout is executed the value is 3
basically in the first example you store every txt[i] inside each function you create with those closures.
In the second one you don't store the txt[i]'s anywhere. you just tell the setTimout function to alert txt[i], which after 1second is the last one created by the for loop.
Upvotes: 1
Reputation: 613
This is a concurrency problem.
setTimeout creates a "thread" for each execution, but won't evaluate the function until the timeout expires.
so, after a second, when the first timeout expires, your for loop has ended (with i
having 3 as value), so accessing the txt[i]
returns undefined.
Try printing the value of i
inside the function with console.log
Upvotes: 0
Reputation: 60007
You need to read up about closures. See this answer How do JavaScript closures work? to understand them.
Upvotes: 1
Reputation: 223073
In the first version, txt[i]
has been bound to a new variable, msg
, which is a different location for each function
being created.
In the second version, i
is the same location for each of the function
s because i
's scope is further up; there isn't a new i
variable being created each time through the loop.
Upvotes: 0