Почему var в цикле приводит к одинаковым значениям в замыканиях?

Почему при использовании var в цикле получаются одинаковые значения? var обладает функциональной, а не блочной областью видимости поэтому все итерации используют одну общую переменную замыкания в цикле захватывают…

Короткий ответ

Что ответить на собеседовании

Почему при использовании var в цикле получаются одинаковые значения? var обладает функциональной, а не блочной областью видимости поэтому все итерации используют одну общую переменную замыкания в цикле захватывают одну и ту же ссылку на переменную var к завершению цикла переменная изменяется, и все замыкания получают её итоговое значение чтобы сохранить значение конкретной итерации, используют let с блочной областью видимости либо создают отдельные области видимости, например через функции причина проблемы — отсутствие блочной области видимости, из-за чего замыкания возвращают одинаковый результат ситуация подчёркивает важность понимания…

Подробный разбор

Ответ с пояснениями

Почему при использовании var в цикле получаются одинаковые значения?

  • var обладает функциональной, а не блочной областью видимости
  • поэтому все итерации используют одну общую переменную
  • замыкания в цикле захватывают одну и ту же ссылку на переменную var
  • к завершению цикла переменная изменяется, и все замыкания получают её итоговое значение
  • чтобы сохранить значение конкретной итерации, используют let с блочной областью видимости либо создают отдельные области видимости, например через функции
  • причина проблемы — отсутствие блочной области видимости, из-за чего замыкания возвращают одинаковый результат
  • ситуация подчёркивает важность понимания областей видимости переменных и замыканий в JS

Подробный ответ

Основной ответ

Если объявить переменную через var в цикле, например for (var i = 0; i < n; i++), все итерации будут обращаться к одной переменной i из функциональной области видимости. Поэтому асинхронные колбэки или отложенные функции, созданные внутри цикла, сохраняют ссылку на одну переменную, а не её отдельную копию. После завершения цикла они читают уже изменённое значение i, обычно последнее.

Ключевые моменты

  • Область видимости var является функциональной, а не блочной: переменная i существует в единственном экземпляре для всего цикла и не создаётся заново на каждой итерации.
  • Асинхронные операции внутри цикла, включая setTimeout и промисы, обращаются к одной изменяемой переменной. Поэтому после завершения цикла все колбэки получают одинаковое значение.
  • ES6 let устраняет проблему: let создаёт отдельную переменную для каждой итерации и использует блочную область видимости, поэтому асинхронная функция получает соответствующее значение.

Практический контекст

Такая ошибка часто встречается в циклах с var, setTimeout, промисами или обработчиками событий. При отложенной отрисовке элементов и асинхронных запросах следует применять let либо создавать замыкание (IIFE), фиксирующее значение на конкретной итерации. В React 18+ и современных приложениях для этого обычно используют let или const внутри цикла.

Практика в реальном времени

Подготовьтесь к следующему собеседованию

Interview Boost учитывает вакансию, резюме и технологии и помогает сформулировать ответ прямо во время интервью.

Начать подготовку