Often, we need to use setTimeout and setInterval
but also need to pass arguments to the function being called. There are a handful of ways to do this.
// Example 1, BAD! :(
var hello = 'Hello World!';
setTimeout("alert('" + hello + "')", 1000);
Example 1 works, but it is not the generally accepted syntax for setTimeout. Passing code as a string relies on the
same behavior as eval, and eval is usually evil for reasons that are beyond the scope of this post... No
pun intended. As an aside, this method is often restricted by Adobe AIR, because
of the implied eval. Here's the common workaround:
// Example 2, better :)
var hello = 'Hello World!';
setTimeout(function() {
alert(hello);
}, 1000);
Using a closure is a much better solution than supplying a string as in the first example, but it can seem bulky. Turning our little alert into a closure has basically doubled the amount of code required! Okay, it's still short, but it's not quite as clear as what we would like to do:
// Example 3, best! :D
var hello = "Hello World";
setTimeout(alert, 1000, hello);
The call to setTimeout in Example 3 is clear about what arguments are being passed, rather than having to
read through the closure to see what variables it might refer to. The good news is that Example 3 already works
on modern browsers (including Adobe AIR). The common implementation for both setTimeout and setInterval
allows you to pass additional arguments by simply... passing additional arguments. Awesome.
The exception to this rule is, of course, IE. At least up through version 7, but probably including version 8, IE
will simply ignore extra arguments supplied to setTimeout and setInterval. It won't even throw an
error, which can make this situation hard to debug (and is probably why this method is not as widely seen as using a
closure). However, here's a bit of code I originally ran across on Web Reflection
that extends this behavior to IE.
// Example 4, keep reading if this is confusing, don't worry...
/*@cc_on
(function(f) {
window.setTimeout = f(window.setTimeout); // overwrites the global function!
window.setInterval = f(window.setInterval); // overwrites the global function!
})(function(f) {
return function(c, t) {
var a = [].slice.call(arguments, 2); // gathers the extra args
return f(function() {
c.apply(this, a); // passes them to your function
}, t);
};
});
@*/
First things first, NO you do not have to retype the above code every time you want to use setTimeout.
Example 4 actually changes the way setTimeout and setInterval behave. You would include Example 4
at the top of your script, first (or early) in the code. Then you can call setTimeout and setInterval
with additional arguments the same way across all browsers. This code makes Example 3 work
everywhere.
Of special note is the conditional comment, /*@cc_on ... @*/. If you use a JavaScript minifier, it may
consider that whole block of code a comment and delete it... Not good. A less semantic but more reliable alternative is to use object
detection to identify IE, typically something like if (("ActiveXObject" in window) && !("opera" in window)) { ... }
I'm a Front-End Engineer at Yahoo! working on the Mail and Messenger teams. I blog about web design and development topics including accessibility, usability, performance, and developing HTML / CSS / JavaScript applications on Appcelerator Titanium and Adobe AIR.
If you're a web developer, you might enjoy Jelo, my JavaScript library.
A few panoramic shots I took at SDCC 2010. #geek http://bit.ly/bwX6GB
JS version of Regex prime number checker:
function isPrime(n) {
return Array(n + 1).join("1")
.search(/^1?$|^(11+?)\1+$/) == -1;
}
Погрузился в пучину EcmaScript5, местами увлекательно, местами нудно =)
Modernizr http://ow.ly/18njQ1
A Collection of 20 HTML5 Video Players - a round-up of JavaScript and html5 alternatives to Flash-based media player... http://ow.ly/18njQ2
jQuery TOOLS - The missing UI library for the Web http://ow.ly/18njQ3
Contactable - A jQuery Plugin | the odin http://ow.ly/18njQ4
Giants vs Dodgers, sweet seats. http://twitpic.com/2ag9pa
@snookca That'll be fixed next week. I promise.
@snookca I was tryna not name names ;) But really that was just par for the course today, pretty hectic day. As I'm sure you know.
Who breaks major stuff after 4pm on Friday? On the last day of the sprint, no less. Tsk. (wasn't me)
Awesome live git tracker for teams: http://www.utsup.com/
RT @DerrenBrown: Blog post: Camera Software Lets You See Into the Past http://bit.ly/9kjVg5
10 invites to the new version of Digg: http://bit.ly/dqM8EV
Threaded vs Evented Servers, great look at the whats and whys. http://bit.ly/bDUEjn #geek
Nav, Context menus, "app-style" toolbars in sample chapter http://bit.ly/csTRY8 of new YUI book http://bit.ly/cJINoV
Add a side-mounted End Call button to your iPhone 4: http://bit.ly/cGxPBD #funny #geekAll original work on this site is covered by a Creative Commons Attribution 3.0 license unless otherwise specified.
You may share or use any code or images from this site in any manner, for free, so long as reasonable effort has been made to give credit where due.
The views expressed in the posts and comments on this blog do not necessarily reflect the views of Yahoo!