Коротка відповідь
juniorЗамикання — це функція, що «зберігає» доступ до змінних свого оточення навіть після завершення виконання зовнішньої функції. Це дозволяє створювати приватні дані та фабрики функцій.
Повне пояснення
Що це і навіщо Замикання (closure) — механізм, який дозволяє внутрішній функції доступатися до змінних зовнішньої. Це корисно для
- створення приватних полів;
- фабрик функцій;
- обробки асинхронних колбеків.
Ключові принципи
- Функція створюється в контексті іншої функції.
- Внутрішня функція зберігає лексичне середовище.
- Змінні не видаляються, поки існує посилання на функцію.
Як це працює При виклику зовнішньої функції створюється новий лексичний контекст. Якщо внутрішня функція повертається, вона зберігає посилання на цей контекст. Після завершення зовнішньої функції, її локальні змінні не видаляються, бо вони «захоплені» замиканням.
Практика і реалізація
function makeCounter() {
let count = 0;
return function () { // замикання
return ++count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
У TypeScript типи автоматично підказуються, але можна явно вказати:
function makeAdder(x: number) {
return (y: number): number => x + y; // замикання
}
Тестування
import { describe, it, expect } from 'vitest';
describe('closure counter', () => {
it('increments correctly', () => {
const c = makeCounter();
expect(c()).toBe(1);
expect(c()).toBe(2);
});
});
Особливості в контексті JS / TS Core
- Замикання працюють з будь‑якими типами даних, включаючи об’єкти та функції.
- У ES6+ можна використовувати
let/const, що забезпечує блочну область видимості. - Під час дебагу важливо розуміти, що змінні в замиканні живуть довше.
Оптимізація та edge cases
- Не створюйте зайвих замикань у циклах без потреби, це може призвести до витоку пам’яті.
- Якщо замикання використовує великі об’єкти, розгляньте
WeakMapдля зберігання.
Часті помилки
- Очікування, що змінна буде «свіжою» після виклику зовнішньої функції.
- Використання
varзамістьlet/const, що призводить до неочікуваних результатів. - Забудова замикання в асинхронних колбеках, що викликає «запізнаний» доступ.
Cheatsheet
function outer() { let a = 1; return function inner() { console.log(a); }; }const fn = outer(); fn(); // 1
Follow‑up питання
- Як замикання впливають на збірку пам’яті?
- Чи можна створити «мутоване» замикання, і що це означає?