Замыкания
1. Замыкания
Замыкание (closure) — это связь между функцией и ее цепочкой областей видимости.
Этот механизм возможен благодаря лексическому окружению. При вызове функции, ее лексическое окружение получает ссылку на ту область видимости, где функция была объявлена (внешнее лексическое окружение), тем самым получая доступ к переменным из нее, буквально удерживая в памяти таблицу доступных переменных.
Итого, замыкание - это термин который описывает способность функции запоминать лексическое окружение в котором она была объявлена, и продолжать получать доступ к переменным из этого лексического окружения вне зависимости от того, где она была вызвана.
Рассмотрим пример функции-счетчика с недоступной извне переменной.
const createCounter = function () {
/*
* Локальная переменная privateValue доступна только в замыкании.
* Получить к ней доступ во внешнем коде невозможно.
*/
let privateValue = 0;
const increment = function () {
privateValue += 1;
console.log(privateValue);
};
return {
increment,
};
};
const counterA = createCounter();
counterA.increment(); // 1
counterA.increment(); // 2
const counterB = createCounter();
counterB.increment(); // 1
counterB.increment(); // 2
counterB.increment(); // 3
Copy
В примере функция createCounter
создаёт локальную переменную privateValue
, а также локальную функцию increment
, которая увеличивает значение privateValue
и выводит значение в консоль.
Функция increment
не содержит собственной локальной переменной privateValue
, но благодаря механизму замыкания ей доступна переменная из внешнего окружения функции createCounter
. В результате она может пользоваться переменной privateValue
, созданной во время вызова функции createCounter
, даже после того, как increment
будет возвращена из вызова createCounter
.
Если заглянуть внутрь counterA
и counterB
используя console.dir()
, наглядно видно механизм замыкания.

Напишем функцию приготовления поваром некого блюда.
const makeDish = function (shefName, dish) {
console.log(`${shefName} is cooking ${dish}`);
};
makeDish('Mango', 'apple pie'); // Mango is cooking apple pie
makeDish('Mango', 'fish'); // Mango is cooking fish
makeDish('Mango', 'beef stew'); // Mango is cooking beef stew
makeDish('Poly', 'muffins'); // Poly is cooking muffins
makeDish('Poly', 'pork chops'); // Poly is cooking pork chops
makeDish('Poly', 'roast beef'); // Poly is cooking roast beef
Copy
Проблема такого подхода в том, что при каждом вызове функции приходится передавать имя повара который будет готовить блюдо. Решить эту проблему можно используя замыкание. Пишем функцию создания шефа с именем, которая возвращает другую функцию для приготовления блюда.
const makeShef = function (name) {
/*
* Параметр name это локальная переменная для функции makeShef.
* Это значит что она будет доступна функции makeDish через замыкание.
*/
return function makeDish(dish) {
console.log(`${name} is cooking ${dish}`);
};
};
const mango = makeShef('Mango');
mango('apple pie'); // Mango is cooking apple pie
mango('beef stew'); // Mango is cooking beef stew
const poly = makeShef('Poly');
poly('pancakes'); // Poly is cooking pancakes
poly('eggs and bacon'); // Poly is cooking eggs and bacon
Copy
Посмотрим в консоль.

2. Дополнительные материалы
Исчерпывающая статья по замыканиям от Preethi Kasireddy, по ссылкам ниже, обязательна к прочтению в свободное от изучения основного материала время.
Last updated