← Назад к вопросам

Что такое WeakMap и WeakSet и когда их следует использовать?

2.3 Middle🔥 191 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

WeakMap и WeakSet в JavaScript

WeakMap и WeakSet — это специальные коллекции в JavaScript, которые обеспечивают слабую ссылку (weak reference) на свои ключи (для WeakMap) или элементы (для WeakSet). Их главная особенность — автоматическое удаление объектов из коллекции, когда на них больше не остаётся сильных ссылок в программе, что позволяет избежать утечек памяти.

Основные характеристики WeakMap

WeakMap — это коллекция пар ключ-значение, где:

  • Ключами могут быть только объекты (не примитивы).
  • Значения могут быть любого типа.
  • Ключи являются слабыми ссылками — если на объект-ключ больше не ссылается никакой другой код, он будет удалён сборщиком мусора, а соответствующая запись исчезнет из WeakMap.
// Пример использования WeakMap
let user = { id: 1 };
let weakMap = new WeakMap();

// Добавляем объект как ключ
weakMap.set(user, 'конфиденциальные данные');

// Пока объект user существует, данные доступны
console.log(weakMap.get(user)); // 'конфиденциальные данные'

// Когда удаляем ссылку на объект...
user = null;

// Объект будет удалён сборщиком мусора,
// а запись автоматически исчезнет из WeakMap

Особенности WeakSet

WeakSet — это коллекция объектов, где:

  • Элементами могут быть только объекты.
  • Каждый объект присутствует в коллекции только один раз (как в обычном Set).
  • Объекты хранятся как слабыми ссылками.
// Пример использования WeakSet
let visitedUsers = new WeakSet();
let user1 = { name: 'Анна' };
let user2 = { name: 'Пётр' };

// Добавляем объекты в WeakSet
visitedUsers.add(user1);
visitedUsers.add(user2);

// Проверяем наличие объектов
console.log(visitedUsers.has(user1)); // true

// Удаляем один объект
visitedUsers.delete(user2);

// Когда объекты больше не используются...
user1 = null;
// Объект user1 будет автоматически удалён из WeakSet

Ключевые отличия от Map и Set

  • Нет перебора и методов получения размера: У WeakMap и WeakSet нет методов keys(), values(), entries(), forEach(), а также свойства size. Это связано с тем, что сборщик мусора может удалить элементы в любой момент, делая перебор ненадёжным.
  • Только для объектов: В отличие от Map и Set, которые могут хранить любые значения.
  • Автоматическая очистка: Не требуют ручного удаления неиспользуемых элементов.

Когда следует использовать WeakMap и WeakSet

Практические применения WeakMap

  1. Хранение приватных данных для объектов

    // Паттерн приватных свойств без использования Symbol или замыканий
    let privateData = new WeakMap();
    
    class User {
      constructor(name) {
        // Используем экземпляр как ключ для приватных данных
        privateData.set(this, { name, secret: Math.random() });
      }
      
      getName() {
        return privateData.get(this).name;
      }
    }
    
    let user = new User('Иван');
    console.log(user.getName()); // 'Иван'
    // У объекта нет публичного доступа к secret
    
  2. Кэширование результатов вычислений

    let cache = new WeakMap();
    
    function expensiveComputation(obj) {
      if (!cache.has(obj)) {
        // Тяжёлые вычисления...
        let result = JSON.stringify(obj) + '_processed';
        cache.set(obj, result);
      }
      return cache.get(obj);
    }
    
    let data = { a: 1, b: 2 };
    console.log(expensiveComputation(data));
    
  3. Хранение метаданных объектов без риска утечек памяти, когда объекты больше не нужны.

Практические применения WeakSet

  1. Отслеживание уникальных событий

    let clickedElements = new WeakSet();
    
    document.addEventListener('click', function(event) {
      if (!clickedElements.has(event.target)) {
        clickedElements.add(event.target);
        console.log('Первое нажатие на элемент');
        // Логика для первого клика
      }
    });
    
  2. Временная маркировка объектов

    // Проверка, был ли объект уже обработан
    let processedObjects = new WeakSet();
    
    function processObject(obj) {
      if (processedObjects.has(obj)) {
        return;
      }
      
      // Обработка объекта...
      processedObjects.add(obj);
    }
    
  3. Управление подписками событий, когда нужно отслеживать, какие объекты уже подписаны.

Преимущества использования

  • Предотвращение утечек памяти: Самый важный аргумент. Когда объекты становятся недостижимыми в основном коде, они автоматически удаляются из коллекций.
  • Автоматическое управление памятью: Не нужно следить за удалением объектов из коллекций вручную.
  • Безопасность: Для WeakMap приватные данные действительно остаются приватными, так как нет возможности получить ключи коллекции.

Ограничения и нюансы

  • Поддержка браузеров: WeakMap и WeakSet поддерживаются во всех современных браузерах, но не работают в IE (кроме IE 11 с частичной поддержкой).
  • Только для объектов: Если нужно хранить примитивные значения, используйте обычные Map/Set.
  • Нет гарантий времени очистки: Сборщик мусора определяет, когда удалять объекты, что может происходить не мгновенно.

Заключение

WeakMap и WeakSet являются специализированными инструментами для работы с объектами, когда важно избежать утечек памяти. Их использование оправдано в сценариях хранения метаданных, кэширования, реализации приватных свойств и отслеживания уникальных объектов. Для большинства повседневных задач обычные Map и Set более удобны благодаря возможности перебора и работе с любыми типами значений, но когда речь идёт о долгоживущих приложениях с большим количеством временных объектов, WeakMap и WeakSet становятся незаменимыми инструментами в арсенале разработчика.

Что такое WeakMap и WeakSet и когда их следует использовать? | PrepBro