I am having an issue regarding a reference.
The snippet is a minimal example that generates buttons with JS, which have events tied to a specific element on a page based on a variable within the code.
stuff = ['a', 'b', 'c']
for (var n of stuff) {
e = document.createElement('button')
e.innerText = 'Button ' + n
e.id = n
e.onclick = function() {
document.getElementById(n).style.backgroundColor = '#dad'
}
document.body.append(e)
}
The buttons work and call their function, although n
seems to "carry through" as a reference.
Attempting to negate this with n.slice()
in the anonymous function does not seem to affect behaviour, even though it should cut out the reference (with the assumption that it returns a new variable, evaluated when the function is defined (instead of later when it is actually called)).
Off the top of my head, I cannot think of a way to pass information into the function in a way that would make each function unique in any way (for my use-case, I want the function to know what element called it, so if there's information in the event object that indicates the element that called it, then that would be very helpful for me also).
I'd also like to avoid passing the function as a string in setAttribute. (which would work, and I'm not even concerned about security at this point, but it feels like a hack).
Is there a canned solution or alternative approach that remedies the unwanted reference?
EDIT: I fixed the code by converting:
for (var n of stuff) {...
to
for (let n of stuff) {...
let
has block-level scoping, and creates a new variable when used as an iterator, the difference in behaviour removes cross-referencing.
(Although I can think of uses where having one shared variable in a for loop would be useful, although declaring a var before the loop would communicate intent more clearly.
tl;dr: let
should probably be used to declare the iterator variable 99% of the time.