Mr Speaker

Closures with self-invoking functions

Just a quick note-to-self... I'm a big fan of using self-invoking anonymous functions to keep stuff out of the global namespace, but I forgot that they are also nifty for keeping variables in scope via closures. Here's the problem... Let's say with have an array that we'd like to populate with functions. The functions simply log their index to the console:

var funcArray = [];		
for( var i = 0; i < 3; i++ ){
	funcArray.push( 
		function(){ console.log( i ); } 
	);
}
// What will these functions log?
funcArray[ 0 ]();
funcArray[ 1 ]();
i = 99; // just for fun
funcArray[ 2 ]();

What will the functions output? If you guessed 3, 3, 99 then you win! Choose anything from the bottom shelf! The reason is that when we log i, JavaScript goes looking for it... up and up the scope chain until it finds it. For us, it'll find it on the window object where we would have incremented it to 3 (after the loop finishes).

Right, so how do we fix it? With a closure! We certainly don't want to pollute the global namespace (more that we already have), so let's wrap our array push in an anonymous self-invoking function and pass the index as a parameter:

var funcArray = [];		
for( var i = 0; i < 3; i++ ){
	(function( i ){
		funcArray.push( 
			function(){ console.log( i ); } 
		);
	})( i );
}

Huzzah! 0,1,2! That's more like it. The function parameter is trapped in our anonymous function scope, ready to do our bidding (I'd probably call the parameter something else, just for clarity - but it's up to you).

For an example of this in the real world, check the source for this Raphaƫl demo. Notice that the angle and colour parameters are passed in to an anonymous function? That's so when the click event handler fires, the colours and angles will be available inside! Nifty!

One Comment

  1. recently I have read lot about closure. Still I find it hard to digest sometime.
    It creates magic. which is not that good.
    It is used at almost all modern framework, so developers are forced to learn it and use it.

    Thursday, December 3, 2009 at 10:18 pm | Permalink
Captcha! Please type 'radical' here: *
How did you find this thingo? *