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