Phil's answer offers a good solution to the specific code you posted (+1), but doesn't explain what the problem was with your original code.
The problem is that the event handler closures get an enduring reference to the index
variable, not a copy of it as of when they're created. So they all see the final value that index
has (divs.length
). For instance, this code
for (index = 0; index < 4; ++index) {
setTimeout(function() {
console.log(index);
}, 100);
}
...will log "4" four times when the timeouts occur, not "0", "1", "2", and "3".
To correct it in the general case where you want to make sure your handler closes over a specific value, use a factory function that generates the event handler function for you, where the event handler closes over the argument you feed the factory function instead of the loop variable:
for(index=0; index<divs.length; index++) {
divs[index].addEventListener("click", createHandler(divs[index], true); //capture click event
}
function createHandler(div) {
return function(){
console.log(div.getAttribute("id"));
};
}
There, the event handler closes over div
, which doesn't change.
Closures are one of the most powerful features of JavaScript. Once you understand how they work (and they're actually a lot simpler than people think), you can use them to really good effect. More: Closures are not complicated