Map и Set в JavaScript: ключи объектов, уникальность и порядок

Map и Set в JavaScript: ключи объектов, уникальность и порядок
Содержание статьи

Map хранит пары «ключ и значение», а Set хранит уникальные значения. В обеих коллекциях объект сравнивается по ссылке. Два отдельно созданных объекта с одинаковыми полями не становятся одним ключом или одним элементом автоматически.

На Mentoring.digital разберём коллекции на учебных данных каталога. Сначала определим, что считается одинаковым товаром: сам объект в памяти или его идентификатор.

Map: объект как ключ

const item = { id: 7 };
const stock = new Map();
stock.set(item, 3);

console.log(stock.get(item));       // 3
console.log(stock.get({ id: 7 }));  // undefined
console.log(stock.size);           // 1

Второй get получает новый объект. Если записи приходят из JSON заново, удобнее использовать стабильный примитивный ключ, например число id. Тогда два чтения одного товара смогут обращаться к одному элементу Map.

get возвращает undefined и при отсутствии ключа, и когда undefined сохранён как значение. Для различения этих ситуаций используйте has. Операции delete и clear удаляют одну запись и очищают коллекцию соответственно.

Set: удаление повторов и его границы

const tags = ["css", "git", "css"];
console.log([...new Set(tags)]); // ['css', 'git']

const first = { id: 7 };
console.log(new Set([first, first]).size);       // 1
console.log(new Set([{ id: 7 }, { id: 7 }]).size); // 2

Для строк это удобный способ удалить точные повторы. Но «CSS» и «css» различаются. Если по требованиям регистр и пробелы не важны, сначала задайте нормализацию. Не применяйте её бездумно к паролям, кодам и другим значениям, у которых регистр может быть значимым.

Уникальность записей по id

const rows = [
  { id: 7, name: "Old" },
  { id: 8, name: "Other" },
  { id: 7, name: "New" },
];
const byId = new Map(rows.map(row => [row.id, row]));
console.log([...byId.values()]);
// [{ id: 7, name: 'New' }, { id: 8, name: 'Other' }]

Здесь последняя запись с id 7 заменила значение. Позиция уже существующего ключа при обновлении не перемещается в конец. Поэтому порядок результата отражает первое добавление ключей, а значения взяты из последних встреченных записей.

Это выбранная политика, а не универсально правильное удаление дублей. Для сохранения первой записи добавляйте её только при !byId.has(row.id). Если повтор означает ошибку, сообщайте о нём отдельно. До построения Map проверьте, что id существует: иначе разные неполные записи могут попасть под общий ключ undefined.

Map, Set или обычный объект

Map удобен как изменяемый словарь, особенно когда ключи не ограничены строками. Set нужен для проверки членства и уникальности. Обычный объект подходит для записи с известными полями, например name и price. Map и Set не сериализуются в полезное содержимое обычным JSON.stringify без явного преобразования.

Проверьте пустой набор, повтор примитива, разные объекты с одинаковым id и отсутствующий id. Для чисел также учтите: NaN считается совпадающим с NaN, а +0 и -0 не образуют разные ключи.

Разобраться с коллекциями помогут курсы JavaScript. Выбор структуры данных для конкретной задачи можно обсудить с наставником по JavaScript.

Похожие статьи по данной теме