WARNING: long (ish) answer
This is copied directly from the article I wrote on the company's internal wiki:
Question: How to use closures in a loop? Quick answer: use the factory function.
for (var i=0; i<10; i++) { document.getElementById(i).onclick = (function(x){ return function(){ alert(x); } })(i); }
or more easily readable version:
function generateMyHandler (x) { return function(){ alert(x); } } for (var i=0; i<10; i++) { document.getElementById(i).onclick = generateMyHandler(i); }
This is often confused by people who are not familiar with javascript or functional programming. This is the result of a misunderstanding of what closure is.
Closing doesn't just pass the value of a variable or even a reference to a variable. Closing captures a variable! The following bit of code illustrates this:
var message = 'Hello!'; document.getElementById('foo').onclick = function(){alert(message)}; message = 'Goodbye!';
Clicking on the 'foo' element will create a window with the message: "Goodbye!". Because of this, using a simple closure in a loop will result in all locks using the same variable, and this variable will contain the last value assigned to it in the loop. For example:
for (var i=0; i<10; i++) { document.getElementById('something'+i).onclick = function(){alert(i)}; }
All elements when pressed will generate a warning window with the number 10. In fact, if we now do i="hello"; , all elements now generate a hi warning! The variable I is divided into ten functions. PLUS - current function / area / context. Think of it as some kind of private global variable that only functions can see.
We need an instance of this variable, or at least a simple reference to the variable instead of the variable itself. Fortunately, javascript already has a mechanism for passing a link (for objects) or a value (for strings and numbers): function arguments!
When a function is called in javascript, the arguments to this function are passed by reference if it is an object or value, if it is a string or number. This is enough to separate the distribution of variables in the closure.
So:
for (var i=0; i<10; i++) { document.getElementById(i).onclick = (function(x){ return function(){ alert(x); } })(i) }