Проблема: цикл использует var, поэтому все замыкания захватывают одну и ту же переменную (i). К моменту вызова функций значение (i) равно (3), поэтому вывод три раза (3).
Пример проблемы: var funcs = []; for (var i = 0; i < 3; i++) { funcs[i] = function() { console.log(i); }; } for (var j = 0; j < 3; j++) { funcs[j](); } // выводит 3, 3, 3
Как исправить (чтобы получить (0,1,2)) — варианты:
1) Использовать let (блочная область, новая привязка на итерацию): var funcs = []; for (let i = 0; i < 3; i++) { funcs[i] = function() { console.log(i); }; } funcs[0](); funcs[1](); funcs[2](); // 0, 1, 2
2) Замыкание через IIFE (для старого окружения без let): var funcs = []; for (var i = 0; i < 3; i++) { (function(x) { funcs[x] = function() { console.log(x); }; })(i); } funcs[0](); funcs[1](); funcs[2](); // 0, 1, 2
3) Использовать bind: var funcs = []; for (var i = 0; i < 3; i++) { funcs[i] = console.log.bind(console, i); } funcs[0](); funcs[1](); funcs[2](); // 0, 1, 2
Коротко: замените var на let или захватите значение текущей итерации в замыкании.
Проблема: цикл использует var, поэтому все замыкания захватывают одну и ту же переменную (i). К моменту вызова функций значение (i) равно (3), поэтому вывод три раза (3).
Пример проблемы:
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = function() { console.log(i); };
}
for (var j = 0; j < 3; j++) { funcs[j](); } // выводит 3, 3, 3
Как исправить (чтобы получить (0,1,2)) — варианты:
1) Использовать let (блочная область, новая привязка на итерацию):
var funcs = [];
for (let i = 0; i < 3; i++) {
funcs[i] = function() { console.log(i); };
}
funcs[0](); funcs[1](); funcs[2](); // 0, 1, 2
2) Замыкание через IIFE (для старого окружения без let):
var funcs = [];
for (var i = 0; i < 3; i++) {
(function(x) {
funcs[x] = function() { console.log(x); };
})(i);
}
funcs[0](); funcs[1](); funcs[2](); // 0, 1, 2
3) Использовать bind:
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = console.log.bind(console, i);
}
funcs[0](); funcs[1](); funcs[2](); // 0, 1, 2
Коротко: замените var на let или захватите значение текущей итерации в замыкании.