Функция setTimeout()
является асинхронной, что означает её выполнение начинается только после завершения всех операций в основном потоке JavaScript. Интересно рассмотреть, что произойдёт, если использовать эту функцию внутри цикла for
.
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 0);
}
Какой результат будет выведен на экран?
Для начала, упростим задачу: уберём setTimeout()
и оставим только console.log(i)
внутри цикла. В таком случае, все операции будут выполняться в основном потоке, и каждое значение i
будет выведено на экран по мере выполнения итераций цикла. В результате, на экране появится последовательность чисел от 0 до 4.
Что происходит с setTimeout()
?
Когда мы используем setTimeout()
внутри цикла, вызов console.log(i)
будет происходить после завершения всех операций в стеке. Это означает, что к моменту выполнения setTimeout()
все итерации цикла будут завершены и значение переменной i
достигнет 5.
Почему на экран выводится одно и то же значение?
Переменная i
объявлена с использованием ключевого слова var
. Это означает, что она имеет функциональную область видимости (а в данном случае — глобальную), и её значение изменяется с каждой итерацией цикла. Поскольку setTimeout()
выполняется после завершения цикла, все пять вызовов console.log(i)
увидят одно и то же значение i
, равное 5.
Итоговый вывод:
Таким образом, на экран 5 раз будет выведено число 5, каждое на новой строке.
Пример кода для лучшего понимания:
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 0);
}
Альтернатива с использованием let
Для тех, кто хочет, чтобы каждый вызов console.log(i)
выводил текущее значение i
на момент итерации, можно использовать ключевое слово let
, которое имеет блочную область видимости:
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 0);
}
В этом случае на экран будут выведены значения от 0 до 4, так как каждая итерация создаёт новую область видимости для переменной i
.