I'm trying to use setTimeout to execute an anonymous function that I pass information into and I'm having trouble. This (hard-coded version) would work just fine:
setTimeout(function(){alert("hello");},1000);
setTimeout(function(){alert("world");},2000);
But I'm trying to take the hello and world from an array and pass them into the function without (a) using global variables, and (2) using eval. I know how I could do it using globals or eval, but how can I do it without. Here is what I'd like to do (but I know it won't work):
var strings = [ "hello", "world" ];
var delay = 1000;
for(var i=0;i<strings.length;i++) {
setTimeout( function(){alert(strings[i]);}, delay);
delay += 1000;
}
Of course strings[i] will be out of context. How can I pass strings[i] into that anonymous function without eval or globals?
This is the very frequently repeated "how do I use a loop variable in a closure" problem.
The canonical solution is to call a function which returns a function that's bound to the current value of the loop variable:
var strings = [ "hello", "world" ];
var delay = 1000;
for(var i=0;i<strings.length;i++) {
setTimeout(
(function(s) {
return function() {
alert(s);
}
})(strings[i]), delay);
delay += 1000;
}
The outer definition function(s) { ... }
creates a new scope where s
is bound to the current value of the supplied parameter - i.e. strings[i]
- where it's available to the inner scope.