Map, Set, WeakMap, WeakSet
Современные коллекции помимо объектов и массивов.
Map
Коллекция пар «ключ-значение» с любыми типами ключей.
const map = new Map();
map.set('name', 'Алиса');
map.set(42, 'ответ');
map.set({ id: 1 }, 'объект-ключ');
map.get('name'); // 'Алиса'
map.get(42); // 'ответ'
map.has('name'); // true
map.size; // 3
map.delete(42);
map.clear();
Отличие от объекта
- Ключи любого типа, не только строки
- Порядок сохраняется
- Есть
size - Итерируется напрямую
- Лучше для частых добавлений и удалений
Создание
const map = new Map([
['a', 1],
['b', 2],
]);
Из объекта:
const map = new Map(Object.entries({ a: 1, b: 2 }));
Перебор
for (const [key, value] of map) {
console.log(key, value);
}
for (const key of map.keys()) {}
for (const value of map.values()) {}
for (const [key, value] of map.entries()) {}
map.forEach((value, key) => {});
В объект
Object.fromEntries(map);
Практика: счётчик
function countWords(words) {
const counts = new Map();
for (const word of words) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
return counts;
}
Set
Коллекция уникальных значений.
const set = new Set([1, 2, 2, 3]);
// Set(3) { 1, 2, 3 }
set.add(4);
set.has(2); // true
set.size; // 4
set.delete(2);
set.clear();
Уникальность
const unique = [...new Set([1, 2, 2, 3])]; // [1, 2, 3]
Объекты сравниваются по ссылке:
new Set([{ a: 1 }, { a: 1 }]).size; // 2
Перебор
for (const value of set) {}
set.forEach((value) => {});
Практика: пересечение
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
const intersection = new Set([...a].filter((x) => b.has(x))); // { 2, 3 }
const union = new Set([...a, ...b]); // { 1, 2, 3, 4 }
const difference = new Set([...a].filter((x) => !b.has(x))); // { 1 }
WeakMap
Map с ключами-объектами и слабыми ссылками:
const wm = new WeakMap();
const key = {};
wm.set(key, 'value');
wm.get(key); // 'value'
Особенности:
- Ключи только объекты
- Не итерируется
- Нет
size - Нет
clear - Если ключ больше не используется — сборщик мусора удалит запись
Где используется WeakMap
Приватные данные:
const privates = new WeakMap();
class User {
constructor(name) {
privates.set(this, { name });
}
getName() {
return privates.get(this).name;
}
}
Кеширование:
const cache = new WeakMap();
function process(obj) {
if (cache.has(obj)) return cache.get(obj);
const result = heavyComputation(obj);
cache.set(obj, result);
return result;
}
WeakSet
Set со слабыми ссылками:
const ws = new WeakSet();
const obj = {};
ws.add(obj);
ws.has(obj); // true
- Только объекты
- Не итерируется
- Нет
size
Когда что
- Map — словарь с любыми ключами
- Set — уникальные значения
- WeakMap — приватные данные, кеш по объектам
- WeakSet — отметки объектов
- Объект — статические данные с строковыми ключами
- Массив — упорядоченные значения
Итоги
Map— ключи любого типаSet— уникальные значенияWeakMap— слабые ссылки, не итерируетсяWeakSet— слабые ссылкиObject.fromEntriesдля преобразования- Spread для массивов