I'm sure I knew this at one point, but I've been away for a while and I can't figure it out anymore.
Let's say I have a collection of buttons ("Button A", "Button B", "Button C", represented by a NodeList retrieved by .getElementsByClassName("button").
I now want to add an EventHandler to these that makes use of some local variables passed by value at the time the handler is created. For a minimal example, let's use:
for (var i = elems.length - 1; i >= 0; i--) {
var inner = elems[i].innerHTML;
elems[i].onclick = function(){window.alert("Clicked on "+inner+" which is element number "+i)};
}
The desired result here would be that, when clicking on Button B, I get
Clicked on Button B which is element number 1
However, all buttons yield
Clicked on Button A which is element number -1
I understand why this happens, but how would I need to change the code to achieve the former? In case this is relevant, in the final eventhandler the i will not be used by itself, but to reference elem[i] again, which is passed into the handler as an argument.
Use let
to declare the variable. This will create a block scope for the variable and will retain the correct value trough out the loop:
for (let i = elems.length - 1; i >= 0; i--) {
Demo:
let elems = document.querySelectorAll('button');
for (let i = elems.length - 1; i >= 0; i--) {
var inner = elems[i].innerHTML;
elems[i].onclick = function(){window.alert("Clicked on "+inner+" which is element number "+i)};
}
<button type="button">Button A</button>
<button type="button">Button B</button>
<button type="button">Button C</button>