WeakMap и WeakSet: слабые ссылки на объекты

Зачем нужны WeakMap и WeakSet? 🧐

В JavaScript обычные Map и Set хранят элементы жёстко — даже если объект больше нигде не используется, он останется в коллекции, пока вы его явно не удалите. Это может привести к утечкам памяти, особенно в сложных приложениях.

WeakMap и WeakSet решают эту проблему с помощью слабых ссылок (weak references). Если объект существует только внутри WeakMap или WeakSet, он может быть автоматически удалён сборщиком мусора (Garbage Collector, GC).

let user = { name: "Alex" };
const weakMap = new WeakMap();

weakMap.set(user, "secret data"); // Добавляем объект в WeakMap
user = null; // Теперь объект { name: "Alex" } может быть удалён GC

💡 Совет: Используйте WeakMap, когда нужно хранить дополнительные данные для объектов, время жизни которых вы не контролируете (например, DOM-элементы или сторонние библиотеки).


Особенности WeakMap 🗝️

  1. Ключи — только объекты. Примитивы (числа, строки и т.д.) не допускаются.
  2. Не поддерживает перебор. Нет методов keys(), values(), entries() или forEach().
  3. Нельзя узнать размер. Свойство size отсутствует.
const weakMap = new WeakMap();
const obj = { id: 1 };

weakMap.set(obj, "value"); // ✅ Работает
weakMap.set("key", "value"); // ❌ Ошибка: ключ должен быть объектом

Практический пример: кеширование результатов 🏎️

Допустим, у нас есть функция, которая выполняет сложные вычисления. Чтобы не считать одно и то же несколько раз, сохраним результаты в WeakMap.

const cache = new WeakMap();

function computeExpensiveValue(obj) {
  if (cache.has(obj)) {
    return cache.get(obj);
  }

  const result = /* ...тяжёлые вычисления... */;
  cache.set(obj, result);
  return result;
}

Когда объект obj больше не нужен, он и связанные с ним данные автоматически удалятся из кеша.


WeakSet: коллекция уникальных объектов 🧩

WeakSet похож на Set, но: - Хранит только объекты. - Не поддерживает перебор и метод size.

const weakSet = new WeakSet();
const user1 = { name: "Alice" };
const user2 = { name: "Bob" };

weakSet.add(user1).add(user2);
console.log(weakSet.has(user1)); // true

user1 = null; // Теперь { name: "Alice" } может быть удалён GC

🔥 Идея: Используйте WeakSet, чтобы отмечать объекты (например, проверенные или обработанные), не мешая их удалению.


Где это применяется в реальности? 🌍

1. Дополнительные данные для DOM-элементов
Храните метаданные для элементов, не влияя на их удаление.

const domData = new WeakMap();
const button = document.querySelector("#myButton");

domData.set(button, { clicks: 0 });
button.addEventListener("click", () => {
   const data = domData.get(button);
   data.clicks++;
});

2. Отслеживание объектов без утечек памяти
Например, список активных пользователей, который не должен мешать GC.


Итог: когда выбирать WeakMap/WeakSet? 🏆

Ситуация Выбор Почему?
Нужно хранить данные для объектов WeakMap Автоматическая очистка
Отметка объектов (без дублей) WeakSet Лёгкость и автоматическое удаление
Требуется перебор коллекции Обычный Map/Set Weak-коллекции не поддерживают итерацию
// Финал: сравнение Map и WeakMap
const map = new Map();
const weakMap = new WeakMap();
let obj = { data: "test" };

map.set(obj, true); // Объект останется в памяти, пока не удалён из Map
weakMap.set(obj, true); // Объект удалится GC, когда станет недостижим

Теперь вы знаете, как работать с WeakMap и WeakSet эффективно и без утечек памяти! 🎉

Скрыть рекламу навсегда

🎥 YouTube: программирование простым языком

Канал, где я спокойно и по шагам объясняю сложные темы — без заумных терминов и лишней теории.

Подходит, если раньше «не заходило», но хочется наконец понять.

▶️ Смотреть курсы на YouTube