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?
Just add a scope around the setTimeout call:
You could write a separate function to set up the timeout:
Then just call that from the loop:
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:
The outer definition
function(s) { ... }
creates a new scope wheres
is bound to the current value of the supplied parameter - i.e.strings[i]
- where it's available to the inner scope.Although not as backward compatible as some of the other answers, thought I'd throw up another option.. this time using bind()!
View demo of it in action