Можно ли использовать массив или объект для хранения уникальных значений в JavaScript
Что проверяют
Знаете ли вы, что для этой задачи в языке есть Set, и понимаете ли, чем плохи самодельные варианты на массиве и объекте. Следом обычно спрашивают, как Set сравнивает объекты и как убрать дубли из массива объектов по id.
Как отвечать
Можно, но оба варианта хуже Set, и стоит объяснить чем:
- массив: уникальность держите сами, проверкой
includesпередpush. Каждая проверка это линейный проход, так что заполнение массива из n элементов стоит O(n²). На десятках элементов неважно, на десятках тысяч заметно; - объект как словарь: ключи уникальны, проверка быстрая. Но ключ всегда строка или символ:
1и"1"склеятся в один ключ, а любой объект превратится в"[object Object]". Целочисленные ключи обходятся по возрастанию, а не в порядке добавления, а проверкаkey in objнайдёт унаследованныйtoString, если не создавать объект черезObject.create(null); Set: хранит значения любого типа, сравнивает по алгоритму SameValueZero (как===, ноNaNравенNaN), проверкаhasв среднем O(1), порядок вставки сохраняется. Дедупликация массива:[...new Set(arr)];- новые методы:
union,intersection,difference,isSubsetOfи другие вошли в стандарт (ES2025) и есть во всех актуальных браузерах, раньше для этого писали циклы; - уникальность по полю: объекты в
Setразличаются по ссылке, поэтому два{ id: 1 }будут двумя элементами. Для дедупликации поidберутMap:new Map(items.map(i => [i.id, i])).
Во фронтенде добавьте практику: Set в состоянии React нельзя мутировать через add, нужно создать новый, например setSelected(prev => new Set(prev).add(id)). Иначе ссылка не изменится и перерисовки не будет.
Где спотыкаются
Ждут, что Set уберёт одинаковые по содержимому объекты. Он сравнивает ссылки, а не поля.
Используют объект со смешанными ключами и получают склейку числа и строки или неожиданный порядок обхода.
Сериализуют Set через JSON.stringify и получают {}. Перед отправкой на сервер или в localStorage его нужно превратить в массив.