Если вы храните кэш в
Map внутри замыкания, то даже после того как объект-ключ становится недоступен, ссылка остается — объект не собирается GC. В больших SPA, API-клиентах или SSR-рендерах это приводит к постепенному росту памяти без видимой причины.Почему WeakMap решает проблему утечек
Замена
Map на WeakMap автоматически удаляет запись при исчезновении последней внешней ссылки на ключ. Это критично для кэширования результатов при обработке временных объектов, например, в middleware или event handlers.function createWeakCache() {
const cache = new WeakMap();
return {
get: (obj) => cache.get(obj),
set: (obj, value) => cache.set(obj, value)
};
}Подводный камень: GC при высокой частоте ключей
WeakMap/WeakSet очищаются только во время сборки мусора. Если вы создаете короткоживущие объекты (меньше 100 мс жизни) и сразу добавляете их в WeakMap, то GC будет запускаться чаще — до десятков раз в секунду. Это проседает CPU в Node.js API или FPS в браузере.
* Плохой паттерн — каждый микротик создавать объекты и помещать их в WeakSet.
* Пример:
seen.add(obj) в цикле генерации 1000 объектов за 1 мс — GC будет чистить постоянно.Практический совет и проверка
1. Не используйте WeakMap/WeakSet для high-frequency cache (миллионы ключей за секунду). Лучше обычный
Map с ручной очисткой или LRU-стратегией.2. Проверяйте профиль GC: Chrome DevTools > Performance > Memory. Если видите частые малые пики GC при короткоживущих объектах — пересмотрите архитектуру.
3. Для долгоживущих объектов (DOM-ноды, классы с временем жизни > 1 секунды) WeakMap безопасен и выгоден.
Производительность
Операции в WeakMap в 2-4 раза медленнее Map (микросекунды). Но ключевая стоимость — GC: чем больше ключей без внешних ссылок, тем чаще GC проверяет их. Это может добавить десятки миллисекунд на сборку при нескольких тысячах ключей.
Вывод:
WeakMap и WeakSet — мощный инструмент против утечек через замыкания, но при high-frequency кэшировании короткоживущих объектов вы рискуете получить нагрузку на GC, а не спасение памяти.