The main issue here has to do with scoping. Let me reduce your example to a more minimal example:
var qtyCallbacks = [];
for (var i = 1; i < 11; i++) {
qtyCallbacks.push(() => console.log(i));
}
for (const callback of qtyCallbacks) {
callback();
}
What's going wrong here? Why is it only logging 11
and not 1-10
?
The issue is that a variable defined with var
are scoped to the nearest function or globally if not in a function. So what does this mean?
It means that each iteration in your for loop refers to the same i
. This isn't an issue if you directly use i
.
for (var i = 1; i < 11; i++) {
console.log(i); // logs 1-10
}
However it does become an issue if you refer to i
in code that is executed at a later point. The reason the initial snippet only logs 11
is because all the callbacks are created, each one referring to the same i
. So when you evoke each callback after the for-loop is complete, they will all refer to the current value (which is 11
).
for (var i = 1; i < 11; i++) {
}
console.log(i); // logs 11
// so if we invoke the callbacks here they all log 11
So how do you solve this issue? The simplest solution is probably to replace var
with let
. let
will create a new variable for each for-iteration. Meaning that each created callback will refer to their own i
and not a shared i
. This also means that you cannot access i
outside of the for-loop.
var qtyCallbacks = [];
for (let i = 1; i < 11; i++) {
qtyCallbacks.push(() => console.log(i));
}
for (const callback of qtyCallbacks) {
callback();
}
console.log(i); // expected error, `i` is only available within the for-block