JavaScript timers – using functions and scope

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 :-) ).

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? :-)

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! :-)

 

Related reading

Posted in Developing,JavaScript,Technology |

11 Comments

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>