Что выведется в консоль в цикле с var
Что проверяют
Знаете ли вы, что у var нет блочной области видимости, и связываете ли это с замыканиями и очередью задач. Вопрос простой, но по ответу видно, говорит человек заученную фразу или понимает, что именно захватил колбэк.
Как отвечать
Разбирать на коде и называть вывод сразу.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// 3, 3, 3var объявлена в функции, а не в блоке, поэтому на весь цикл существует одна переменная. Все три колбэка замкнулись на неё же. К моменту, когда сработают таймеры, синхронный код давно закончился, цикл дошёл до тройки и вышел, и каждый колбэк читает текущее значение общей переменной.
С let вывод будет 0, 1, 2: на каждой итерации создаётся своя привязка, в которую копируется значение, так что каждый колбэк видит свою копию. Если console.log стоит прямо в теле цикла, оба варианта печатают 0, 1, 2: разница проявляется только на отложенном вызове. Стоит назвать и старые обходные приёмы: обёртка в немедленно вызываемую функцию или передача значения третьим аргументом setTimeout.
Где спотыкаются
Называют 0, 1, 2, забыв, что колбэк выполнится после цикла. Нулевая задержка не означает «сейчас»: задача встаёт в очередь и ждёт, пока опустеет стек вызовов.
Называют 2. Цикл заканчивается, когда условие стало ложным, то есть уже после инкремента до тройки, и именно её видят колбэки.
Объясняют всё поднятием переменной. Поднятие отвечает лишь на вопрос, почему переменная одна на функцию, а сам эффект даёт общее замыкание. И на уточнение про let отвечают «он не поднимается»: поднимается, но до объявления лежит во временной мёртвой зоне.