A quirk with JavaScript closures

I keep running into this obstacle every now and then. Consider this example:

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

I wanted an array of three closures, each printing a different number to the console when called. Instead, each prints 3 (or, rather, whatever the value of the variable “i” happens to be).

I am not exactly sure about the reason, but presumably this happens because the “i” in each lambda refers to the variable “i” itself, not to its binding from the creation time of the function.

One solution is to enforce the bindings explicitly on each iteration, like this:

for (var i = 0; i < 3; i++)
  (function(v) {
    q.push(function() { console.log(v); });
  })(i);

Or use Underscore.js [1], which is what I actually do:

_([1,2,3]).each(function(i) {
  q.push(function() { console.log(i); });
});

Links

[1]