JavaScript timers – using functions and scope

Tweet Follow @robertnyman

This article is also available in Russian.

Today I thought I’d introduce you to timers in JavaScript and how to use scope to make your life easier.

How we started

If you’ve been writing JavaScript for a while, you probably wrote your first timer calls like this (most likely, this guess for those of you who are new to JavaScript as well):

setTimeout("setBGColor()", 1000);
function setBGColor () {
	document.body.style.backgroundColor = "#f00";
}

All fine and well, unless that if you start to validate your JavaScript with a tool such as JSLint, you’ll soon realize that using string as the first parameter in the call to setTimeout is frowned upon (this of course goes for setInterval as well). Instead, you’re told to use functions. The reason for this is that for a string parameter to work, you need to concatenate strings, just like the eval statement, and it’s both a security hazard as well as a stability risk.

Using a function as the parameter

Following the advice we were given, we’re rewriting the above example with a function instead of a string. It would look a bit like this:

setTimeout(function () {
	document.body.style.backgroundColor = "#f00";
}, 1000);

Instead of an anonymous function within the setTimeout call, this could of course also be a function pointer:

setTimeout(setBGColor, 1000);
function setBGColor () {
	document.body.style.backgroundColor = "#f00";
}

Note that this looks pretty much like our first example above with a string, except that the surrounding quotation marks and following parentheses are removed. I’ll show below why an anonymous function right there in the code is more useful than a function pointer.

Working with variables and references

All of the above code is fine and well, but what if we want to apply this style to whatever element that calls the function? And perhaps want to set the color at runtime too?

For the sake of making it easy, let’s call a function as soon as the window has loaded:

window.onload = function () {
	setElmBGColor.call(document.body, "#ff0");
};

As you can see, we call the function in a certain element’s context (document.body, in this case) using the call method, and we also send in our desired color: “#ff0” (yellow, for those who don’t read hex spacer ).

setElmBGColor function – using a string for evaluation

If we were to use the string version of setTimeout to create the setElmBGColor function, it would have to look like this:

function setElmBGColor (bgColor) {
	currentElm = this;
	setTimeout("currentElm.style.backgroundColor = '" + bgColor + "'", 1000);
}

Notice that the currentElm has to be global (the var keyword preceding it has been omitted), because setTimout is run in a global context, i.e. the window object’s (remember, children, global variables are bad). Also, it becomes a matter of puzzling strings together, and, as stated above, could become a security concern. Not very nice.

setElmBGColor function – using a function and scope

Instead, let’s look at using scope to help us out here:

function setElmBGColor (bgColor) {
	var currentElm = this;
	setTimeout(function () {
		currentElm.style.backgroundColor = bgColor;
	}, 1000);
}

setElmBGColor function – using a function with scope and closure

We could of course get a little more fancy, using scope and a closure, to get rid of the currentElm variable and solely use what context we’re in as the parameter for the function used in the setTimeout call:

function setElmBGColor (bgColor) {
	setTimeout(function (elm) {
		return function () {
			elm.style.backgroundColor = bgColor;
		};
	}(this), 1000);
}

A scalable and flexible solution

With all solutions mentioned here in this last part, it means that the setElmBGColor function could be used for any element with any color. For instance, let change this:

setElmBGColor.call(document.body, "#ff0");

to this:

setElmBGColor.call(document.getElementById("container"), "#00f");

and it would work right out of the box. Quite nice, isn’t it? spacer

Conclusion

I hope I managed to inspire you a little to play around with JavaScript syntax, and explained why using functions instead of strings in timers is a lot more versatile and powerful.

Happy scripting! spacer

 

Related reading

  • Explaining JavaScript scope and closures
Follow @robertnyman RSS
Posted in Developing,JavaScript,Technology | Tweet

11 Comments

  • RSS feed for comments on this post
  • RSS feed for comments on all posts
  • spacer Henrik Pejer says:
    December 17, 2008 at 9:26

    Yepp, thats timers like i’ve never done em before.

    Good job man!

    Reply
  • spacer Robert Nyman says:
    December 17, 2008 at 16:32

    Henrik,

    Thanks!

    Reply
  • spacer Chris says:
    December 18, 2008 at 9:50

    Thank you very much for this article. spacer
    There’s one last thing I don’t really understand: In your example “Scope And Closure” you use scope in order to pass arguments to the anonymous function but also pass this as an argument. Why isn’t it possible to pass multiple arguments like this?

    Reply
  • spacer Robert Nyman says:
    December 18, 2008 at 10:08

    Chris,

    Thanks!
    You can send in any number of parameters you want to – this was just to simplify the object reference itself. But, just remember that the value of those parameters will be their value when the closure was created, i.e. when you caled setElmBGColor.

    Reply
  • spacer Stefan Van Reeth says:
    December 18, 2008 at 21:36

    There was a time I hunted the net for tutorials like this one. Nowadays I find this to be just basic stuff (off course πŸ˜‰ ). But man would I have loved to read this then. And for those who wonder: yes I’ve been guilty too. Until the day I heard the word ‘closure’, I used strings as parameters for timers. No worries, I’m cured now.

    Robert, without any kidding, you’re really a fine teacher. Exact, to the point and still concerning alternatives. On top of that you pour it all into very readable texts that are quite enjoyable to read.

    Ever thought of writing some JavaScript book? You would have at least one reader if the latter chapters would be a little more hardcore spacer

    Reply
  • spacer Robert Nyman says:
    December 19, 2008 at 16:32

    Stefan,

    Stop it, you’re just making me blush!
    But thank you! spacer

    Not sure the book is going to happen. to be honest, I’ve had a few options/alternatives, but so far I’ve turned them – mostly because it takes a lot of time, effort and energy to write a book.

    Reply
  • ??????? » [Web] ???? says:
    April 9, 2009 at 4:00

    […] JavaScript timers – using functions and scope […]

    Reply
  • spacer coder says:
    May 3, 2011 at 10:25

    Hi Robert, one more translation of your great javascript articles into russian is here coders.ask-ru.net/question.aspx?qid2=290 . I really like to read your blog, it’s very useful!

    Reply
  • spacer Robert Nyman says:
    May 3, 2011 at 11:07

    coder,

    Great, thank you!

    Reply
  • JavaScript Reference Links | kabayview.com says:
    May 21, 2012 at 16:50

    […] JavaScript Timers – Using Functions and Scope – Robert Nyman […]

    Reply
  • Thank you for 2008 – Happy New Year! - Robert's talk says:
    November 27, 2012 at 10:41

    […] JavaScript timers – using functions and scope […]

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *