Twitter About Home

When is a Javascript closure not really a closure?

This has frustrated me one time too many, so I’ve finally taken the time to figure it out. What should the following code do?

Published Sep 17, 2007
var closures = [];
for(var i = 0; i < 10; i++)
	closures[i] = function() { alert(i); }
closures[3]();

It alerts “3”, right? Wrong. It alerts “10”. It turns out that the Javascript runtime will only open one closure context per function call. So, the anonymous functions in the array all reference the same closure context, and so they’re all seeing the same variable i in whatever state it’s reached when they’re finally invoked.

This can be a pain. Really, sometimes I want closures to wrap up the complete state of execution at the instant they’re defined, particularly when defining event handlers in a loop.

You can work around it with code like this:

var closures = [];
for(var i = 0; i < 10; i++)
	closures[i] = function(i) {
				return function() { alert(i); }
			  }(i);
closures[3]();

Ta da! Now it alerts “3”. All we’re doing is creating a ‘wrapper’ anonymous function from which the real one gets returned. The act of invoking the wrapper function creates a new closure context.

Note: this isn’t a bug in Javascript - it’s intended behaviour. Learn more about Javascript closures

READ NEXT

Geolocation is easier (and cheaper) than you think

Most of the time when you’re surfing the web, or creating web applications, you don’t expect real geography to be involved. Historically it’s been tricky to identify with any accuracy or reliability the physical location of your visitors, and might even be said to contravene the spirit of the web. But if what if you really do want to take action based on where they’re coming from?

Published Sep 13, 2007