Scope и замыкания
↑ 1.4 JavaScript: основы · ← Предыдущая · → Следующая
Зачем это на собесе
Замыкания — один из главных вопросов. Нужно объяснить, что такое лексическое окружение, и привести примеры применения.
Объяснение
Scope (область видимости): глобальный, функциональный, блочный, модульный. Лексическая область определяется местом объявления, а не вызова. Поиск переменной идёт по цепочке scope от внутреннего к внешнему.
Замыкание — функция вместе с ссылкой на лексическое окружение, в котором она создана. Функция «помнит» внешние переменные даже после завершения внешней функции.
function counter() {
let count = 0; // приватное состояние
return { inc: () => ++count, get: () => count };
}
const c = counter();
c.inc(); c.inc(); c.get(); // 2
// Фабрика функций
const multiplier = (k) => (x) => x * k;
const double = multiplier(2);
// Классическая ловушка
for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)); // 3 3 3
for (let j = 0; j < 3; j++) setTimeout(() => console.log(j)); // 0 1 2
// в старом коде: (function (n) { setTimeout(() => console.log(n)); })(i); // IIFE
// Мемоизация
const memo = (fn, cache = new Map()) => (x) => cache.has(x) ? cache.get(x) : (cache.set(x, fn(x)), cache.get(x));Применения: приватные данные (модульный паттерн), каррирование и частичное применение, мемоизация, debounce/throttle, обработчики событий, коллбэки, once.
Нюансы и подводные камни
- Замыкание удерживает всё окружение, а не только используемые переменные (движки оптимизируют, но не гарантируют): возможны утечки памяти при захвате больших объектов.
- Обработчики событий и таймеры, захватившие DOM-узлы, не освобождают память до удаления.
- Циклы с
varи асинхронными коллбэками — типичная ошибка. - Функции в цикле создаются заново на каждой итерации: учитывайте стоимость.
Практика
- Реализуйте
once(fn),memoize(fn), счётчик с приватным состоянием. - Исправьте цикл с
varтремя способами. - Найдите замыкание, удерживающее лишнее, в профилировщике памяти.
Вопросы с ответами
Что такое замыкание?
Функция вместе с ссылкой на внешнее лексическое окружение, сохраняющая доступ к его переменным.
Зачем замыкания?
Приватное состояние, фабрики функций, мемоизация, debounce, коллбэки.
Может ли замыкание вызвать утечку памяти?
Да, если функция живёт долго и удерживает большие внешние объекты.