В этой статье мы рассмотрим заглушку JavaScript и попытаемся понять, как она работает в деталях.

Постановка задачи

Что будет на выходе для этой заглушки?

const func = () => {
    for (var i = 1; i < 5; i++) {
        setTimeout(() => console.log(i), 1000);
    }
}
func();

Отвечать

Распространенный неправильный ответ

Самый распространенный ответ, который мы получаем от новичков:

Вывод будет 1, 2, 3, 4

Но, очевидно, это неправильно, все не так просто, как кажется.

Правильный ответ

Вывод будет 5, 5, 5, 5

Живая работа

Давайте посмотрим, как это работает в браузере.

Чтобы проверить в браузере,

  1. Я создал html-файл и добавил кнопку, по нажатию которой мы можем вызвать функцию.
  2. Просто чтобы различать каждый console.log, я добавил текущую временную метку Date.
  3. И добавил отладчик в console.log для проверки стека вызовов и закрытия.

Обсудить, почему так происходит?

Задав этот простой вопрос, интервьюер затронул сложные темы JavaScript, такие как цикл событий, замыкание и подъем.

Разберемся, что происходит во время исполнения.

  1. Прежде всего следует отметить, что мы используем ключевое слово var, которое поднимет переменную i в родительскую область, и она будет сохранена в куче.
  2. Во-вторых, мы вызываем webAPIsetTimeout внутри цикла for. Таким образом, все четыре функции console.log будут помещены в Очередь обратного вызова.
  3. Как только выполнение цикла for завершено (он достигает критического состояния, которое в нашем случае равно 5), он удаляется из стека вызовов, а затем цикл событий вводит все четыре console.log из Очереди обратного вызова.
  4. Но в этот момент переменная i присутствует в куче и ее значение равно 5. Вот почему все четыре console.log регистрируют 5 в браузере.

Как мы можем это исправить?

Мы можем исправить это, просто изменив var на let. Это сделает область видимости блока переменной i.

Если вы хотите узнать больше об этих сложных темах в деталях, прочтите эти замечательные статьи на Medium.

  1. https://medium.com/@Rahulx1/understanding-event-loop-call-stack-event-job-queue-in-javascript-63dcd2c71ecd
  2. https://medium.com/@allansendagi/javascript-fundamentals-call-stack-and-memory-heap-401eb8713204