Привет, ребята! У меня возникла проблема с замыканиями в JavaScript, когда я использую циклы. Вот пример кода:
let functions = [];
for (var i = 0; i < 3; i++) {
functions[i] = function() {
console.log('Значение:', i);
};
}
functions.forEach(f => f());
Я ожидал, что он выведет:
Значение: 0
Значение: 1
Значение: 2
Но вместо этого получаю:
Значение: 3
Значение: 3
Значение: 3
Та же проблема возникает с обработчиками событий и асинхронным кодом. Как это исправить? Я пробовал использовать let вместо var, но не уверен, что это правильное решение. Может, кто-нибудь объяснит, в чем тут дело, и как сделать так, чтобы код работал как задумано? Буду благодарен за помощь!
Дело в том, что var создает одну переменную на весь цикл. К моменту вызова функций i уже равно 3. Самое простое решение - заменить var на let. Это создаст новую переменную i для каждой итерации:
for (let i = 0; i < 3; i++) {
functions[i] = function() {
console.log(‘Значение:’, i);
};
}
Так каждая функция получит свое значение i. Это современный и правильный подход к решению такой проблемы.
эта проблема связана с особенностями var в js. когда ты использоуешь var, переменная i становится глобальной для всей функции, и к моменту вызова функций из массива она уже равна 3.
чтобы исправить, можно использовать let вместо var - это создаст блочную область видимости для i в каждой итерации цикла.
или можно использовать замыкание, создавая функцию внутри цикла:
for (var i = 0; i < 3; i++) {
functions[i] = (function(num) {
return function() {
console.log(‘значение:’, num);
};
})(i);
}
так каждая функция получит свою копию i
Да, проблема в области видимости var. Еще один способ решить - использовать метод forEach с передачей индекса:
functions = Array.from({length: 3}, (_, i) => () => console.log(‘Значение:’, i));
Так создается массив функций, каждая из которых замыкает свой индекс. Просто, эффективно и современно. Как тебе такой вариант?