I'm trying to set five staggered function calls (happening one second apart). That part works fine. What doesn't work is, I can't pass values 0 through 4 into the callback function. It just passes '5' each time. I can't seem to figure out why and how to fix it.
Code:
?function callback(num) { console.log(num); } for (var i = 0, loadDelay = 1000; i < 5; ++ i, loadDelay += 1000) setTimeout(function() { callback(i); }, loadDelay);
Result:
5 5 5 5 5
Desired result:
0 1 2 3 4
That's because you create a closure. So the function you pass to setTimeout share the same i instances. In the browser that supports the standards (not IE) you could have:
setTimeout
i
setTimeout(callback, loadDelay, i);
See: http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#timers
Otherwise you have to actually bind the argument to the function:
bind
setTimeout(callback.bind(undefined, i), loadDelay);
See: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
If the browser doesn't support ES5 bind method, you can either implement the shim present in the link above, or manually doing something like:
setTimeout(function(index){ return function() { callback(index) } }(i), loadDelay);
But I would say it's more readable using bind and it's worthy to implement the shim. You can actually use this: https://github.com/kriskowal/es5-shim
To add es5 capabilities (where is possible) in the browser that don't support es5 natively.
1.4m articles
1.4m replys
5 comments
57.0k users