В предыдущей статье рассматривались области видимости и различия между let, const и var. Эти темы напрямую приводят к замыканиям. Замыкание — не отдельный механизм и не «продвинутая техника», а естественное следствие того, как JavaScript работает с функциями и переменными.
Если кратко, замыкание возникает тогда, когда функция продолжает использовать переменные из внешней области после того, как эта внешняя область перестала выполняться.
Отправная точка: локальная переменная
function calculateTotal(price) {
const tax = 0.2;
return price + price * tax;
}
calculateTotal(100);
Здесь:
- tax создаётся при вызове функции
- используется внутри неё
- после завершения функции больше не существует
Это обычное поведение локальных переменных.
Вложенная функция и расширение области доступа
function createCalculator() {
const tax = 0.2;
function calculate(price) {
return price + price * tax;
}
return calculate;
}
const calculateTotal = createCalculator();
calculateTotal(100);
Этот код выглядит похожим, но ведёт себя принципиально иначе.
Функция createCalculator завершила выполнение, но:
- функция calculate продолжает существовать
- она использует переменную tax
- значит, JavaScript сохраняет эту переменную в памяти
Почему JavaScript сохраняет переменные
JavaScript не «удерживает» переменные специально.
Он просто следует простому правилу: данные не удаляются, пока на них есть ссылка.
В данном случае:
- ссылка есть у функции calculate
- поэтому tax остаётся доступной
Это и есть замыкание.
Что такое замыкание без формальных определений
На практике можно считать, что:
- функция «запоминает» переменные, которые были доступны при её создании
- эти переменные становятся частью её внутреннего состояния
Это не копия значений и не снимок состояния, а живая связь с переменными.
Замыкание как способ хранения состояния
Рассмотрим задачу, которая регулярно встречается в коде.
Нужно:
- один раз задать параметры
- использовать их много раз
- не хранить их в глобальной области
function createUserFormatter() {
const prefix = 'User: ';
return function (name) {
return prefix + name;
};
}
const formatUser = createUserFormatter();
formatUser('Alex');
formatUser('Maria');
prefix:
- создаётся один раз
- не доступен напрямую
- используется при каждом вызове функции
Это состояние, сохранённое через замыкание.
Почему не использовать глобальные переменные
Тот же код без замыкания:
const prefix = 'User: ';
function formatUser(name) {
return prefix + name;
}
Формально код работает, но:
- prefix доступен отовсюду
- его легко переопределить
- поведение функции зависит от внешнего окружения
Замыкание делает поведение функции более предсказуемым.
Несколько независимых состояний
const adminFormatter = createUserFormatter();
const guestFormatter = createUserFormatter();
Каждый вызов createUserFormatter:
- создаёт собственную область
- собственный prefix
- независимое состояние
Это невозможно реализовать корректно с глобальными переменными.
Ошибка, которая выглядит странно без понимания замыканий
const loggers = [];
for (var i = 1; i <= 3; i++) {
loggers.push(function () {
console.log('Item', i);
});
}
На первый взгляд кажется, что каждая функция должна помнить своё значение i.
Но все функции замыкаются на одну и ту же переменную.
Решение уже известно:
for (let i = 1; i <= 3; i++) {
loggers.push(function () {
console.log('Item', i);
});
}
Теперь каждая итерация создаёт новую переменную, и замыкания работают ожидаемо.
Где замыкания используются в реальном коде
Замыкания лежат в основе:
- модулей
- фабрик функций
- конфигурации
- инкапсуляции данных
- обработчиков событий
Пример, который легко узнать:
function createConfig() {
const env = 'production';
return {
getEnv() {
return env;
}
};
}
Итог статьи
На этом этапе важно зафиксировать несколько идей:
- Замыкания — следствие областей видимости
- Функции продолжают иметь доступ к внешним переменным
- Переменные живут, пока используются
- Замыкания позволяют хранить состояние и скрывать данные
В следующей статье будет рассмотрено, как JavaScript работает с типами данных, потому что именно типы определяют, какое состояние хранится и как оно может изменяться.
21.01.2026
0
23
Комментарии
0