Map и Set в JavaScript: понятное руководство с примерами для начинающих
Запрос «Map и Set в JavaScript: понятное руководство с примерами» часто задают новички и продолжающие разработчики. Эти коллекции — фундамент современного JS: они упрощают работу с уникальными значениями, быстрым поиском по ключу любого типа и кешированием без утечек памяти. Разберёмся, чем они лучше Object и Array и как применять на практике.
Что такое Map и Set и когда их использовать
Map — упорядоченная коллекция пар ключ–значение, где ключом может быть любой тип (включая объект). Set — набор уникальных значений любого типа. Если вам нужны ассоциативные ключи не только-строки — берите Map. Если нужно хранить уникальные элементы и быстро проверять наличие — берите Set.
Map: ключи любого типа, предсказуемый порядок, удобная итерация
const map = new Map();
map.set('name', 'Alice');
map.set(42, 'answer');
const objKey = { id: 1 };
map.set(objKey, 'value for object');
console.log(map.get('name')); // Alice
console.log(map.get(objKey)); // value for object
console.log(map.size); // 3
for (const [key, value] of map) {
console.log(key, '=>', value);
}
В отличие от обычного объекта, ключами Map могут быть объекты. Это устраняет типичные баги со строковой сериализацией ключей.
// Плохая практика с Object: ключ-объект превращается в строку
const o = {};
const a = { x: 1 }, b = { x: 1 };
o[a] = 'A';
o[b] = 'B';
console.log(o[a]); // 'B' — ключи столкнулись как '[object Object]'
// Правильно с Map
const m = new Map();
m.set(a, 'A');
m.set(b, 'B');
console.log(m.get(a)); // 'A'
console.log(m.get(b)); // 'B'
Практика: частотный словарь
const words = ['js', 'map', 'js', 'set', 'map', 'map'];
const counts = new Map();
for (const w of words) {
counts.set(w, (counts.get(w) || 0) + 1);
}
console.log([...counts.entries()]);
// [['js', 2], ['map', 3], ['set', 1]]
Set: уникальные значения и быстрые операции над множествами
Set хранит только уникальные значения. Частый кейс — быстро убрать дубликаты из массива.
const ids = [1, 2, 2, 3, 1, 4];
const unique = [...new Set(ids)];
console.log(unique); // [1, 2, 3, 4]
Операции над множествами удобно реализуются на Set:
const A = new Set([1, 2, 3]);
const B = new Set([3, 4]);
const union = (a, b) => new Set([...a, ...b]);
const intersection = (a, b) => {
const bHas = new Set(b);
return new Set([...a].filter(x => bHas.has(x)));
};
const difference = (a, b) => {
const bHas = new Set(b);
return new Set([...a].filter(x => !bHas.has(x)));
};
console.log([...union(A, B)]); // [1, 2, 3, 4]
console.log([...intersection(A, B)]); // [3]
console.log([...difference(A, B)]); // [1, 2]
WeakMap и WeakSet: без утечек памяти
WeakMap хранит пары «ключ-объект → значение», а WeakSet — только объекты. Главное: они не препятствуют сборке мусора. Если на объект-ключ больше нет ссылок, запись автоматически исчезнет из WeakMap/WeakSet. Нельзя итерироваться по их содержимому и узнавать размер — это важно для предсказуемости GC.
Практика: кеширование измерений DOM без утечек
const sizeCache = new WeakMap();
function measure(node) {
if (sizeCache.has(node)) return sizeCache.get(node);
const rect = node.getBoundingClientRect();
const size = { w: rect.width, h: rect.height };
sizeCache.set(node, size);
return size;
}
document.querySelectorAll('.item').forEach(el => {
console.log(measure(el));
});
// Когда .item удалятся из DOM и не будет других ссылок на элементы,
// соответствующие записи исчезнут из WeakMap сами собой.
Практика: приватные данные для экземпляров класса
const _private = new WeakMap();
class Counter {
constructor() {
_private.set(this, { count: 0 });
}
inc() {
const state = _private.get(this);
state.count++;
return state.count;
}
}
const c = new Counter();
console.log(c.inc()); // 1
console.log(c.inc()); // 2
// Нет риска утечек: когда c станет недостижим, его данные из WeakMap исчезнут.
Инициализация один раз на элемент с WeakSet
const initialized = new WeakSet();
function initWidget(el) {
if (initialized.has(el)) return; // уже инициализировано
// ... навешиваем события, создаём состояние и т.д.
initialized.add(el);
}
document.querySelectorAll('[data-widget]').forEach(initWidget);
Конвертации между коллекциями
// Object → Map и обратно
const user = { name: 'Bob', age: 30 };
const mapFromObj = new Map(Object.entries(user));
const objFromMap = Object.fromEntries(mapFromObj);
// Array пар → Map
const pairs = [['x', 1], ['y', 2]];
const m = new Map(pairs);
// Set → Array и обратно
const set = new Set([1, 2, 3]);
const arr = [...set];
const setAgain = new Set(arr);
Типичные ошибки и как их избежать
- Случайная строковая сериализация ключей в Object. Если ключ — объект или число, лучше Map, иначе возможны коллизии.
- Попытка итерироваться по WeakMap/WeakSet или узнать size. Это запрещено по дизайну из‑за GC.
- Сравнение объектов по значению в Set/Map. Сравнение идёт по ссылке, не по содержимому. Два одинаковых литерала-объекта — разные элементы.
- Хранение временных DOM‑узлов в обычной Map. Используйте WeakMap/WeakSet, чтобы избежать утечек при удалении элементов.
Когда что выбирать
- Object: небольшие фиксированные словари, JSON‑сериализация, прототипные возможности.
- Map: динамические ключи любого типа, много вставок/удалений, предсказуемая итерация.
- Set: уникальные значения, быстрые проверки наличия, операции над множествами.
- WeakMap/WeakSet: связывание данных с жизненным циклом объектов, кеши и флаги инициализации без утечек памяти.
Мини‑чеклист лучших практик
- Нужны ключи‑объекты? Выбирайте Map/WeakMap.
- Нужны уникальные элементы и частые проверки has? Выбирайте Set/WeakSet.
- Для больших динамических словарей Map быстрее и удобнее, чем Object.
- Для одноразовой дедупликации массива используйте new Set(arr).
- Избегайте итерации по WeakMap/WeakSet — используйте Map/Set, если нужно обходить элементы.
Хотите системно прокачать основы и уверенно применять коллекции, модули, замыкания и асинхронность на практике? Рекомендую практический курс «Программирование на JavaScript с Нуля до Гуру 2.0» — много задач, разбор типичных ошибок и понятные объяснения для уверенного старта и роста.
Итоги
Map и Set в JavaScript упрощают повседневные задачи с уникальными значениями и ассоциативными структурами, а WeakMap и WeakSet помогают писать код без утечек памяти. Освоив эти коллекции, вы будете выбирать правильный инструмент под задачу и писать чище, быстрее и надёжнее.
-
Создано 03.06.2026 17:05:22
-
Михаил Русаков

Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.