A function remembers the variables around it, not the values they had when it was created. If a loop creates functions that use a variable shared by all iterations, every one of them sees the last value by the time it's called.
A function is only reported if it uses a variable from outside itself that's assigned in the loop, after the loop, or in another function. A const and a let declared inside the loop are always safe.
Configure
Off by default. To turn it on:
[lint.rules]
"no-loop-func" = "error" # or "warn"
Examples
Reported:
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function () {
select(i); // always buttons.length
};
}
let page = 0;
while (page < pages.length) {
tasks.push(() => download(pages[page]));
page++;
}
Not reported. Each iteration gets its own i and page:
for (let i = 0; i < buttons.length; i++) {
buttons[i].onclick = function () {
select(i);
};
}
for (const page of pages) {
tasks.push(() => download(page));
}
Not reported, because retries never changes once the loop has started:
let retries = 3;
for (const page of pages) {
tasks.push(() => download(page, retries));
}
Not reported, because the function is called on the spot and nowhere else:
for (var i = 0; i < buttons.length; i++) {
(function () {
select(i);
})();
}