Какая разница между Set и WeakSet?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Сложный
#JavaScript #Коллекции #База JS

Краткий ответ

Set и WeakSet — это оба коллекции для хранения уникальных значений, но у них есть важные отличия:

  1. Set может хранить любые значения (строки, числа, объекты), а WeakSet только объекты 📦
  2. Set можно перебирать, а WeakSet нельзя 🔍
  3. WeakSet автоматически удаляет объекты, которые больше нигде не используются 🗑️
// Set — хранит любые значения
const set = new Set([1, 2, 'hello', {}]);
 
// WeakSet — только объекты
const obj = {};
const weakSet = new WeakSet([obj]);

Полный ответ

Представь, что Set — это обычный ящик, куда можно складывать что угодно: игрушки, книги, одежду. А WeakSet — это магический ящик, который сам выбрасывает вещи, когда они никому больше не нужны! 📦✨

Основные отличия

Типы значений

// Set может хранить всё
const set = new Set();
set.add(1);        // число ✅
set.add('text');   // строка ✅
set.add({});       // объект ✅
 
// WeakSet только объекты
const weakSet = new WeakSet();
// weakSet.add(1);     // ❌ Ошибка!
// weakSet.add('text'); // ❌ Ошибка!
weakSet.add({});       // ✅ Только объекты

Перебор элементов

const set = new Set([1, 2, 3]);
 
// Set можно перебирать
for (const item of set) {
  console.log(item); // 1, 2, 3
}
 
const weakSet = new WeakSet([{a: 1}, {b: 2}]);
 
// ❌ WeakSet нельзя перебирать!
// for (const item of weakSet) // Ошибка!

Как работает WeakSet

WeakSet — как друг, который помнит только тех людей, с которыми ты всё ещё общаешься. Если человек ушёл из твоей жизни (никто больше не держит на него ссылку), WeakSet сам забудет о нём! 🧠

Автоматическая очистка

let obj = { name: 'Иван' };
const weakSet = new WeakSet([obj]);
 
// Когда obj больше никем не используется
obj = null;
 
// Объект автоматически удалится из WeakSet
// Сборщик мусора позаботится об этом 🗑️

Когда использовать Set

Для хранения любых уникальных значений

// Уникальные пользователи
const uniqueUsers = new Set();
 
// Уникальные теги
const tags = new Set(['js', 'css', 'html', 'js']); 
// Будет только ['js', 'css', 'html']

Когда нужен перебор

// Нужно пройтись по всем элементам
const numbers = new Set([1, 2, 3]);
 
numbers.forEach(num => {
  console.log(num); // 1, 2, 3
});

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

Для отслеживания объектов

// Отслеживаем уже обработанные объекты
const processed = new WeakSet();
 
function process(obj) {
  if (processed.has(obj)) {
    return 'уже обработан';
  }
  
  processed.add(obj);
  return 'обработан';
}

Для предотвращения повторной обработки

// Проверяем, не обрабатывали ли мы этот узел
const visited = new WeakSet();
 
function traverse(node) {
  if (visited.has(node)) {
    return; // Уже были здесь
  }
  
  visited.add(node);
  // Обрабатываем узел...
}

Частые ошибки

Попытка хранить примитивы в WeakSet

// ❌ Ошибка!
const weakSet = new WeakSet();
// weakSet.add('строка'); // TypeError!
// weakSet.add(123);      // TypeError!
 
// ✅ Правильно
const obj = {};
weakSet.add(obj); // Только объекты!

Ожидание перебора WeakSet

// ❌ Нельзя перебирать WeakSet
const weakSet = new WeakSet([{a: 1}]);
// weakSet.forEach(item => {}); // Ошибка!

Простые правила

  1. Set — универсальный ящик для любых значений 📦
  2. WeakSet — магический ящик только для объектов 🧙
  3. Set можно перебирать, WeakSet — нельзя 🔍
  4. WeakSet сам очищается, Set — нет 🗑️
  5. Используй Set для общих задач, WeakSet для отслеживания объектов 🎯

Понимание разницы между Set и WeakSet помогает выбрать правильный инструмент для решения задачи и избежать проблем с памятью! 💪


Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪