> Пример замыкания с внутренней функцией и предмет замыкания в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Кэтрид Диджитал

Стек: JavaScript

> Пример ответа

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

Замыкание - это комбинация функции и лексического окружения, в котором она была объявлена. Внутренняя функция "замыкает" переменные внешней функции даже после завершения её выполнения. Предмет замыкания - доступ к переменным внешней области видимости, которые не уничтожаются сборщиком мусора, пока существует внутренняя функция.

Подробное объяснение

В JavaScript каждая функция при создании получает скрытое свойство [[Environment]], которое ссылается на текущее лексическое окружение. Когда внутренняя функция вызывается позже, она ищет переменные сначала в своём окружении, затем в окружении, на которое ссылается [[Environment]], и так далее по цепочке.

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

Предмет замыкания - не просто доступ к переменным, а именно сохранение их состояния между вызовами. Это позволяет создавать приватные данные, фабрики функций, частичное применение аргументов и мемоизацию.

На практике

Замыкания широко используются в реальном коде:

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

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

Пример кода

JAVASCRIPT
function createCounter() {
let count = 0; // переменная из внешней области видимости
return function() {
count += 1; // внутренняя функция замыкает count
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

Ещё пример с захватом переменной, а не значения:

JAVASCRIPT
function createFunctions() {
const funcs = [];
for (var i = 0; i < 3; i++) {
funcs.push(function() {
return i;
});
}
return funcs;
}
const funcs = createFunctions();
console.log(funcs[0]()); // 3, а не 0 - все функции замыкают одну и ту же переменную i

Как отвечать на собеседовании

Начни с определения: замыкание - это функция вместе с её лексическим окружением. Затем объясни механизм: внутренняя функция сохраняет ссылку на окружение внешней, поэтому переменные не удаляются. Приведи пример с счётчиком. Подчеркни, что замыкание захватывает переменную, а не её значение - это часто проверяют отдельно. Упомяни практическое применение: инкапсуляция, фабрики, мемоизация. Если спросят про var в цикле - объясни проблему и решение через let или IIFE.

Что проверяет интервьюер

Интервьюер проверяет:

  • понимание лексической области видимости и цепочки областей видимости
  • знание механизма [[Environment]] и работы сборщика мусора
  • умение объяснить разницу между захватом значения и захватом ссылки
  • способность применить замыкания на практике, а не только дать определение
  • понимание связи замыканий с памятью и потенциальными утечками

Типичные ошибки

  • утверждение, что замыкание - это просто вложенная функция (это необходимое, но не достаточное условие)
  • путаница между замыканием и областью видимости
  • непонимание, что замыкание захватывает переменную, а не её текущее значение
  • забывание про утечки памяти: если замыкание хранится долго, оно удерживает всё окружение
  • неумение объяснить поведение var в цикле с замыканиями
  • попытка объяснить через "копирование значений" - это неверно, происходит захват ссылки

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью