Что такое Weak Reference (слабая ссылка) в JavaScript?

«Что такое Weak Reference (слабая ссылка) в JavaScript?» — вопрос из категории JavaScript, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Weak Reference (слабая ссылка) — это ссылка на объект, которая не защищает этот объект от сборки мусора (Garbage Collection). Если на объект остались только слабые ссылки, сборщик мусора может удалить его, и слабые ссылки автоматически станут undefined (или коллекция их очистит).

В JavaScript слабые ссылки реализованы через две встроенные коллекции: WeakMap и WeakSet.

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

  1. Ключами могут быть только объекты (не примитивы).
  2. Нет итераторов. Нельзя получить список всех ключей или значений (keys(), values(), entries()), нет свойства size. Это связано с тем, что перебор зависит от состояния сборки мусора, которое недетерминировано.
  3. Автоматическая очистка. Если объект-ключ удалён сборщиком мусора, запись автоматически удаляется из WeakMap, а объект — из WeakSet.

Практическое применение WeakMap: Часто используется для хранения приватных или вспомогательных данных объекта, не вмешиваясь в его жизненный цикл и не вызывая утечек памяти.

// Пример: хранение приватных метаданных для объектов
const privateData = new WeakMap();

class User {
    constructor(name) {
        // this - объект, используем его как ключ в WeakMap
        privateData.set(this, { 
            name: name,
            secretToken: Math.random().toString(36).substr(2) 
        });
    }

    getName() {
        // Получаем данные по ссылке на текущий экземпляр
        return privateData.get(this).name;
    }
}

let user = new User('Анна');
console.log(user.getName()); // 'Анна'
console.log(privateData.get(user)); // { name: 'Анна', secretToken: '...' }

// Когда объект user будет удалён (например, вышел из области видимости),
// запись в WeakMap также будет автоматически удалена сборщиком мусора.
// Это предотвращает утечку памяти.
user = null; 
// Теперь privateData не удерживает старый объект в памяти.

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