Цикл з var і setTimeout
Через дві речі одночасно:
var- функціональна область видимості. У цикліfor (var i = 0; i < 3; i++) { ... }створюється одна зміннаiна всю функцію, а не нова на кожну ітерацію. Усі колбекиsetTimeout"замикають" те саме значенняi.setTimeoutвиконується пізніше. Колбеки потрапляють у чергу макрозадач і запускаються після того, як поточний JS-стек спорожніє. До моменту першого виклику таймера цикл уже завершено, іiмає фінальне значення (наприклад, 3).
Симптом
javascript
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// 3
// 3
// 3Як виправити
Варіант 1 - let (блокова область видимості):
javascript
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0); // 0, 1, 2
}Варіант 2 - IIFE/замикання з передачею поточного i:
javascript
for (var i = 0; i < 3; i++) {
(function (j) {
setTimeout(() => console.log(j), 0); // 0, 1, 2
})(i);
}Варіант 3 - передати аргументом у setTimeout:
javascript
for (var i = 0; i < 3; i++) {
setTimeout(j => console.log(j), 0, i); // 0, 1, 2
}Варіант 4 - bind:
javascript
for (var i = 0; i < 3; i++) {
setTimeout(console.log.bind(null, i), 0); // 0, 1, 2
}Коротко:
varдає одну "спільну" змінну на весь цикл, аsetTimeoutзапускається, коли цикл уже закінчено. Використовуйтеletабо ізолюйте значення через замикання/аргументи.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.