Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Користь від замикань». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Замикання** - це здатність функції зберігати доступ до змінних свого лексичного оточення навіть після завершення зовнішньої функції, в якій вона була створена. Це дозволяє реалізовувати приватні дані, фабрики функцій, кешування та обробники подій без класів чи глобальних змінних. **Ключове:** замикання створюється автоматично щоразу, коли функція оголошується всередині іншої функції.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке замикання > **Замикання** - це функція, яка "пам'ятає" лексичну (зовнішню) область, > навіть якщо вона виконується **поза цією областю**. Простіше кажучи: > Замикання - це здатність функції **дістатися до змінних з місця, де вона була створена**, > а не звідти, де вона викликана. --- ## Приклад 1 - базовий ```javascript function outer() { let count = 0; function inner() { count++; console.log(count); } return inner; } const counter = outer(); counter(); // 1 counter(); // 2 counter(); // 3 ``` Що відбувається: - `outer()` повертає `inner()`; - `inner()` запам'ятав змінну `count` зі свого лексичного оточення; - навіть після того як `outer()` завершилася, `count` **не зникає**; - це і є **замикання** - "збережена пам'ять" функції. --- ## Приклад 2 - приватні змінні ```javascript function createUser(name) { let score = 0; return { getName() { return name; }, addScore() { score++; }, getScore() { return score; } }; } const alice = createUser('Alice'); alice.addScore(); alice.addScore(); console.log(alice.getName(), alice.getScore()); // Alice 2 ``` Тут `score` - приватна змінна: вона недоступна ззовні (`alice.score` не існує), але доступна із замикань `getScore` і `addScore`. Так реалізуються **інкапсуляція** і **приватні дані** без класів. --- ## Приклад 3 - генератори функцій (фабрики) ```javascript function makeMultiplier(factor) { return function(num) { return num * factor; }; } const double = makeMultiplier(2); const triple = makeMultiplier(3); console.log(double(5)); // 10 console.log(triple(5)); // 15 ``` `factor` "живе" всередині кожної функції. Тобто кожна функція "пам'ятає", з яким множником її створили. --- ## Приклад 4 - обробники подій ```javascript function setupButton(id) { let clicks = 0; document.getElementById(id).addEventListener('click', () => { clicks++; console.log(`Клік по кнопці ${id}: ${clicks}`); }); } setupButton('save'); setupButton('cancel'); ``` Кожен обробник "пам'ятає" свою змінну `clicks`, навіть після виходу з `setupButton`. --- ## Приклад 5 - кешування (memoization) ```javascript function memoize(fn) { const cache = {}; return function(arg) { if (cache[arg]) { console.log('З кешу:', arg); return cache[arg]; } const result = fn(arg); cache[arg] = result; console.log('Обчислено:', arg); return result; }; } const square = memoize(x => x * x); square(4); // Обчислено: 4 square(4); // З кешу: 4 ``` `cache` зберігається між викликами завдяки замиканню. --- ## Як це працює "під капотом" Коли функція створюється, JS формує **лексичне оточення** (Lexical Environment) - об'єкт, де зберігаються всі змінні, оголошені всередині. Якщо внутрішня функція використовує змінні із зовнішньої області, вона **запам'ятовує посилання** на це оточення. Тому навіть після завершення зовнішньої функції внутрішні функції можуть звертатися до її змінних. --- ## Замикання створюються автоматично Не потрібно робити нічого особливого - **щоразу**, коли ти створюєш функцію **всередині іншої**, JS створює замикання. ```javascript function outer() { const a = 42; return function() { console.log(a); // замикання }; } ``` --- ## Де застосовуються замикання в реальному житті | Сценарій | Приклад | |---|---| | **Приватні дані** | Ховаємо змінні всередині функції | | **Фабрики функцій** | Генератори, конфігуровані обробники | | **Модулі та інкапсуляція** | Розділення логіки без глобальних змінних | | **Кешування (memoization)** | Зберігаємо результати обчислень | | **Лічильники і стан** | Утримуємо стан між викликами | | **Callback-и та обробники подій** | Доступ до зовнішніх даних всередині функції | | **Функціональне програмування** | Currying, partial application, compose тощо |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.