Loop Variables and Events

When you place event handlers (or listeners) inside of a loop the end result isn't always what you intended. Consider the following example loop where the ten elements in the page with id="lnk0" through id="lnk9" each display an alert when clicked simply to demonstrate the value that is contained in the variable "i" at that time (you'd never use an alert in your final code, you'd replace it with whatever is supposed to run when the event is triggered):

for (i = 0; i < 10; i++) {
document.getElementById('lnk'+i).onclick = function() {alert(i);};

If you were to actually run this code then clicking on any of those elements would display the value "10" in all of the alerts. Is that what you expected? Well possibly if you understand how the above JavaScript works. Is that what you want? Probably not. Where you add event processing inside of a loop then you probably want the function attached to the event to use the values based on what they held at the time that the function was attached to the event, not the value that it has at the time the event was triggered.

What we need to do is to capture the value that the variable had at the time the function is assigned to the event and use that value when the function is called rather than the value that the variable has at that later time. To do this we use a closure. Consider the following version of the above code:

var loopClick = function(i) {
return function() {alert(i);};
for (i = 0; i < 10; i++) {
document.getElementById('lnk'+i).onclick = loopClick(i);

Now instead of directly attaching the function to the event handler we are returning the function to be attached from a new function that we have added to the code. This new function is run immediately inside the loop and so the values passed into it are those at the time that those variables have at the time that function is run, in this case loopClick is called ten times with the values 0 through 9 being passed. Because it is being passed into that function through a parameter the value of that variable inside of the loopclick function has local scope within that function. All references to that valiable within the function that it is returning therefore use the value that was passed to the function at the time was run even though the returned function doesn't get run until later. This extension of the scope of local variables that are still accessible after the function that defined them is what is known as a closure.

With this slight modification to the way that we attach functions to events our code now alerst the value between 0 and 9 that was the original loop value at the time the function was attached to the event rather than the 10 that the variable has at the time of triggering the event.


This article written by Stephen Chapman, Felgall Pty Ltd.

go to top

FaceBook Follow
Twitter Follow