Что еще можно сделать с помощью замыканий в JavaScript кроме счетчика
Что проверяют
Видите ли вы замыкания в реальном коде, а не только в учебном счётчике. Интервьюер ждёт несколько живых применений и понимания, чем замыкание платит за удобство. Следом часто дают задачу: написать debounce или объяснить ловушку с var в цикле.
Как отвечать
Коротко напомните суть: функция запоминает лексическое окружение, в котором создана, и видит его переменные, даже когда внешняя функция уже вернулась. Дальше примеры из работы:
- приватное состояние: переменные внутри фабрики недоступны снаружи, наружу торчит только API. Для классов сейчас есть поля
#private, но модульный паттерн на фабриках никуда не делся; - фабрики и частичное применение:
const withTax = rate => price => price * (1 + rate), каррирование, настраиваемые валидаторы; debounceиthrottle: идентификатор таймера хранится в замыкании между вызовами. Частая задача на лайвкодинге;- мемоизация: кэш в замыкании. Лучше
Mapи проверка черезhas, иначе закэшированный0или пустая строка посчитаются промахом; once: функция выполнится только один раз, флаг живёт в замыкании;- обработчики и колбэки: обработчик события или
setTimeoutпомнит данные момента, когда его создали; - хуки React:
useState,useEffectиuseCallbackпостроены на замыканиях. Отсюда проблема устаревшего замыкания (stale closure), когда эффект видит старое значение пропа, и смысл массива зависимостей.
Хорошо закончить ценой: замыкание держит переменные окружения, пока жива сама функция. Забытый подписчик, который ссылается на большой объект, становится утечкой памяти.
Где спотыкаются
Путают замыкание с контекстом this. Замыкание про переменные окружения, а this определяется способом вызова и к замыканию не относится, кроме стрелочных функций, которые берут его снаружи.
Не могут объяснить цикл с var и setTimeout, который печатает одно и то же число. С let каждая итерация получает свою привязку, с var она одна на всю функцию.
Пишут мемоизацию через if (cache[key]) на обычном объекте. Ложные результаты никогда не достанутся из кэша, а ключ через JSON.stringify склеивает undefined и null в одно значение.