Выбор ответа Junior Области видимости и замыкания спрашивают часто обновлено

Почему let в цикле чинит setTimeout

Вопрос

Почему for (let i = 0; i < 3; i++) setTimeout(() => console.log(i)) выводит 0 1 2, а с var выводит 3 3 3?

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: let даёт новую привязку i на каждую итерацию, а var одна на функцию. Спецификация для for с let создаёт отдельное окружение на каждую итерацию и копирует туда текущее значение счётчика.

Варианты ответа

  1. let даёт новую привязку i на каждую итерацию, а var одна на функциюправильный ответ
  2. С let колбэки setTimeout внутри цикла выполняются синхронно, сразу
  3. let копирует значение в колбэк при вызове setTimeout, а var передаёт ссылку
  4. С var таймеры срабатывают в обратном порядке, и выводится последнее значение

Разбор

Спецификация для for с let создаёт отдельное окружение на каждую итерацию и копирует туда текущее значение счётчика. Каждая стрелка замыкает свою i. С var переменная одна, к запуску колбэков цикл закончился и она равна 3. Колбэки таймеров асинхронны в обоих случаях. «Копирование значения в колбэк» неверно: замыкание всегда хранит ссылку на переменную, просто с let переменных три. Порядок таймеров с одинаковой задержкой сохраняется.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.