Проверяет понимание области видимости var, замыканий и асинхронности в JavaScript на примере цикла с setTimeout.
Когда вы используете var внутри цикла, переменная объявляется один раз и принадлежит всей функции (или глобальной области). Внутри setTimeout создаётся замыкание, которое захватывает ссылку на эту переменную, а не её текущее значение. К моменту, когда таймеры срабатывают, цикл уже завершился, и переменная содержит последнее значение.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Вывод: 3, 3, 3Здесь все три колбэка ссылаются на одну и ту же переменную i. После завершения цикла i равна 3, поэтому все вызовы выводят 3.
Замыкание — это функция, которая запоминает своё лексическое окружение, включая переменные, объявленные вне её. В данном случае каждая функция внутри setTimeout является замыканием, которое захватывает переменную i из внешней области. Так как var не создаёт блочную область видимости, все замыкания видят одну и ту же переменную.
Использование let решает проблему, потому что let создаёт новую переменную для каждой итерации цикла. Каждое замыкание захватывает свою собственную копию i.
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Вывод: 0, 1, 2Альтернативно можно использовать IIFE (немедленно вызываемую функцию) для создания новой области видимости с var.
Понимание этой особенности важно для избежания ошибок в асинхронном коде. Используйте let или const для блочной области видимости, чтобы каждое замыкание получало правильное значение. Это особенно полезно при работе с циклами и обработчиками событий.
Frontend developer
Ментор по Frontend
Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства
Записаться на консультацию