Замыкания
Замыкание — это когда функция запоминает и сохраняет доступ к переменным из внешней области видимости, даже после того как внешняя функция завершила свою работу.
Это происходит потому, что в JavaScript каждая функция «запоминает» окружение, в котором она была создана — даже если она выполняется позже, в другом месте.
Простой пример:
function createUserManager() {
let userCount = 0;
return function() {
userCount++;
return `Пользователей: ${userCount}`;
};
}
const addUser = createUserManager();
console.log(addUser()); // "Пользователей: 1"
console.log(addUser()); // "Пользователей: 2"
console.log(addUser()); // "Пользователей: 3"
Здесь:
createUserManagerсоздаёт переменнуюuserCountи возвращает внутреннюю функцию- После вызова
createUserManager()внешняя функция завершается — её стек должен быть очищен - Но внутренняя функция (
addUser) продолжает «помнить» и использоватьuserCount - Это и есть замыкание: внутренняя функция замыкает на переменную из внешней области
Пример 1: Настройки темы приложения
function createThemeManager() {
let currentTheme = "light";
return {
getTheme() { return currentTheme; },
setTheme(theme) { currentTheme = theme; },
toggleTheme() { currentTheme = currentTheme === "light" ? "dark" : "light"; }
};
}
const theme = createThemeManager();
theme.setTheme("dark");
console.log(theme.getTheme()); // "dark"
theme.toggleTheme();
console.log(theme.getTheme()); // "light"
Тема хранится в замыкании — не загрязняет глобальное пространство, доступна только через контролируемые методы.
Пример 2: Обработчик событий с контекстом
function setupButtonHandler(buttonId, userId) {
document.getElementById(buttonId).addEventListener("click", function() {
console.log(`Кнопка ${buttonId} нажата пользователем ${userId}`);
});
}
setupButtonHandler("profileBtn", 456);
// При клике выведет: "Кнопка profileBtn нажата пользователем 456"
// Даже если функция setupButtonHandler уже завершилась — замыкание сохранило userId
Пример 3: Каррированные функции
Каррирование — это преобразование функции, принимающей несколько аргументов, в последовательность функций, каждая из которых принимает один аргумент. Основано на замыканиях.
function multiply(a) {
return function(b) {
return function(c) {
return a * b * c;
};
};
}
const multiplyBy2 = multiply(2);
const multiplyBy2And5 = multiplyBy2(5);
console.log(multiplyBy2And5(3)); // 30
// Или в одну строку:
console.log(multiply(2)(5)(3)); // 30
Здесь каждая вложенная функция «запоминает» значение a, затем b, используя замыкание. Это позволяет создавать переиспользуемые частичные версии функций — например, для форматирования, валидации или настройки API-запросов.
Важно понимать:
- Замыкание не создаёт копию переменной — оно ссылается на неё
- Если переменная меняется — замыкание видит новое значение
- Замыкания могут вызывать утечки памяти, если держат ссылки на большие объекты без необходимости
Замыкания — мощный инструмент. Используйте их для инкапсуляции данных, создания приватных состояний, управления контекстом в обработчиках и реализации каррированных функций — особенно в React, Vue или чистом JavaScript без фреймворков.