Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про JavaScript: closure, reference type, JavaScript, scope, hoisting

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

Вопрос проверяет понимание механизма замыканий в JavaScript и особенностей захвата ссылочных типов, что важно для избежания ошибок в асинхронном коде и циклах.

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

Замыкание запоминает не значение переменной, а ссылку на неё. Если переменная изменяется после создания замыкания, то при вызове функции будет использовано последнее значение. Это часто приводит к неожиданному поведению в циклах с асинхронными операциями, например, при использовании var или при захвате объектов.

Длинный ответ

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

Замыкание в JavaScript — это функция, которая запоминает свою внешнюю область видимости, даже после того, как внешняя функция завершила выполнение. Однако, если замыкание захватывает переменную ссылочного типа (например, объект, массив или переменную, объявленную через var), оно сохраняет не копию значения, а ссылку на саму переменную. Это означает, что любые изменения этой переменной после создания замыкания будут видны при вызове замыкания.

Пример с циклом и var

Классический пример — использование var в цикле for. Переменная i объявляется один раз и переиспользуется на каждой итерации. Все замыкания, созданные внутри цикла, ссылаются на одну и ту же переменную i. Когда замыкания выполняются (например, после завершения цикла), они видят последнее значение i.

for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // выведет 3 три раза
  }, 100);
}

В этом примере каждое замыкание внутри setTimeout захватывает переменную i по ссылке. К моменту выполнения таймеров цикл уже завершился, и i равна 3. Поэтому все три вызова выводят 3.

Решение с let или дополнительной функцией

Использование let в цикле создаёт новую переменную для каждой итерации, поэтому замыкание захватывает уникальное значение.

for (let i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // выведет 0, 1, 2
  }, 100);
}

Другой способ — создать новую область видимости с помощью немедленно вызываемой функции (IIFE), передавая текущее значение как аргумент.

for (var i = 0; i < 3; i++) {
  (function(j) {
    setTimeout(function() {
      console.log(j); // выведет 0, 1, 2
    }, 100);
  })(i);
}

Захват объектов

Аналогичная проблема возникает при захвате объектов. Если замыкание использует объект, который позже мутируется, то при вызове замыкания оно увидит изменённое состояние.

let obj = { value: 1 };
const closure = () => console.log(obj.value);
obj.value = 2;
closure(); // выведет 2, а не 1

Это поведение может быть как полезным (например, для реактивности), так и источником ошибок, если разработчик ожидает, что замыкание запомнит значение на момент создания.

Вывод

Понимание того, что замыкания захватывают ссылки, а не значения, критично для написания предсказуемого кода. Особенно это важно при работе с асинхронными операциями, циклами и обработчиками событий. Используйте let, const или создавайте новые области видимости, чтобы избежать неожиданного поведения.

Frontend developer

tech
tech
tech
tech
tech
tech
tech
tech
tech

Ментор по Frontend

Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства

Записаться на консультацию

Уровень

  • Рейтинг:

    5

  • Сложность:

    5

Навыки

  • JavaScript

    JavaScript

Ключевые слова

#closure

#reference type

#JavaScript

#scope

#hoisting

Подпишись на React Developer в телеграм

Frontend developer

tech
tech
tech
tech
tech
tech
tech
tech
tech

Ментор по Frontend

Полное сопровождение до оффера — без дорогих курсов, с оплатой после трудоустройства

Записаться на консультацию