Set
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Объект Set
позволяет хранить уникальные значения любого типа, будь то примитивы или ссылки на объекты.
Описание
Объекты "Set" - это коллекция значений. Значение в Set
может встречаться только один раз; оно уникально в коллекции. Вы можете перебирать элементы набора в порядке вставки. Порядок вставки соответствует порядку, в котором каждый элемент был успешно вставлен в коллекцию методом add()
(то есть, когда был вызван add()
, в наборе ещё не было такого элемента).
Спецификация требует реализации наборов, "которые в среднем обеспечивают время доступа, сублинейное количеству элементов в коллекции". Следовательно, он может быть представлен внутренне в виде хэш-таблицы (с поиском O(1)), дерева поиска (с поиском O(log(N))) или любой другой структуры данных, при условии, что сложность выше, чем O(N).
Сравнение значений
При добавлении нового элемента в Set происходит проверка, добавлялся ли такой элемент ранее. Эта проверка использует специальный алгоритм сравнения значений SameValueZero. (Раньше использовался алгоритм SameValue, в котором значения 0
и -0
считаются разными. Смотрите браузерную поддержку ниже). Это означает, что NaN
считается равным NaN
(не смотря на то что NaN !== NaN
), а все другие значения считаются равными в соответствии с семантикой оператора ===
.
Производительность
Метод has
проверяет наличие значения в Set
используя алгоритм, который в среднем работает быстрее поэлементного перебора добавленных ранее элементов. В частности этот алгоритм работает быстрее чем метод [Array.prototype.includes
](/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/includes на массиве, который хранит столько же элементов сколько сравниваемый объект Set
.
Конструктор
Set()
-
Создаёт новый объект
Set
.
Статические свойства
get Set[@@species]
-
Функция-конструктор, которая используется для создания производных объектов.
Свойства экземпляра
Set.prototype[@@toStringTag]
-
Начальное значение
@@toStringTag
свойства - строка"Set"
. Это значение используется вObject.prototype.toString()
. Set.prototype.size
-
Возвращает количество значений в объекте
Set
.
Методы экземпляра
Set.prototype.add()
- : Вставляет новый элемент с указанным значением в объект
Set
, если вSet
ещё нет элемента с таким же значением.
- : Вставляет новый элемент с указанным значением в объект
Set.prototype.clear()
- : Удаляет все значения из объекта
Set
.
- : Удаляет все значения из объекта
Set.prototype.delete()
- : Удаляет элемент, связанный с переданным значением, и возвращает логическое значение, подтверждающее, был ли элемент успешно удалён или нет.
Set.prototype.has(value)
впоследствии вернетfalse
.
- : Удаляет элемент, связанный с переданным значением, и возвращает логическое значение, подтверждающее, был ли элемент успешно удалён или нет.
Set.prototype.has()
- : Возвращает логическое значение, утверждающее, присутствует ли элемент с заданным значением в объекте
Set
или нет.
- : Возвращает логическое значение, утверждающее, присутствует ли элемент с заданным значением в объекте
Set.prototype[@@iterator]()
- : Возвращает новый объект итератора, который выдает значения для каждого элемента в объекте
Set
в порядке вставки.
- : Возвращает новый объект итератора, который выдает значения для каждого элемента в объекте
Set.prototype.values()
- : Возвращает новый объект итератора, который выдает значения для каждого элемента в объекте
Set
в порядке вставки.
- : Возвращает новый объект итератора, который выдает значения для каждого элемента в объекте
Set.prototype.keys()
- : Аналог
Set.prototype.values()
.
- : Аналог
Set.prototype.entries()
- : Возвращает новый объект итератора, который содержит массив
[value, value]
для каждого элемента в объектеSet
в порядке вставки.
Map
, но в случаеSet
ключ (key) каждой записи совпадает с её значением (value).- : Возвращает новый объект итератора, который содержит массив
Set.prototype.forEach()
- : Вызывает
callbackFn
один раз для каждого значения, присутствующего в объектеSet
в порядке вставки. Если указан параметрthisArg
, он будет использоваться в качестве значенияthis
для каждого вызоваcallbackFn
.
- : Вызывает
Примеры
Использование объекта Set
const mySet1 = new Set();
mySet1.add(1); // Set(1) { 1 }
mySet1.add(5); // Set(2) { 1, 5 }
mySet1.add(5); // Set(2) { 1, 5 }
mySet1.add("текст"); // Set(3) { 1, 5, 'текст' }
const o = { a: 1, b: 2 };
mySet1.add(o);
mySet1.add({ a: 1, b: 2 }); // o ссылается на другой объект, так что это нормально
mySet1.has(1); // true
mySet1.has(3); // false, поскольку 3 не был добавлен в набор
mySet1.has(5); // true
mySet1.has(Math.sqrt(25)); // true
mySet1.has("Текст".toLowerCase()); // true
mySet1.has(o); // true
mySet1.size; // 5
mySet1.delete(5); // удаляет элемент 5 из set
mySet1.has(5); // false, 5 был удалён
mySet1.size; // 4, поскольку мы удалили одно значение
mySet1.add(5); // Set(5) { 1, "текст", {...}, {...}, 5 } - ранее удаленный элемент будет добавлен как новый элемент, он не сохранит свое первоначальное положение до удаления
console.log(mySet1); // Set(5) { 1, "текст", {…}, {…}, 5 }
Итерация по объекту Set
Итерация наборов проходит по элементам в порядке вставки.
for (const item of mySet1) {
console.log(item);
}
// 1, "текст", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5
for (const item of mySet1.keys()) {
console.log(item);
}
// 1, "текст", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5
for (const item of mySet1.values()) {
console.log(item);
}
// 1, "текст", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5
// ключ и значение здесь одинаковы
for (const [key, value] of mySet1.entries()) {
console.log(key);
}
// 1, "текст", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5
// Преобразуем объект Set в объект Array с помощью Array.from
const myArr = Array.from(mySet1); // [1, "текст", {"a": 1, "b": 2}, {"a": 1, "b": 2}, 5]
// следующее также будет работать, если запустить его в HTML-документе
mySet1.add(document.body);
mySet1.has(document.querySelector("body")); // true
// преобразование между Set и Array
const mySet2 = new Set([1, 2, 3, 4]);
console.log(mySet2.size); // 4
console.log([...mySet2]); // [1, 2, 3, 4]
// пересечение можно представить следующим образом
const intersection = new Set([...mySet1].filter((x) => mySet2.has(x)));
// разность можно представить следующим образом
const difference = new Set([...mySet1].filter((x) => !mySet2.has(x)));
// итерироваться можно с помощью forEach()
mySet2.forEach((value) => {
console.log(value);
});
// 1
// 2
// 3
// 4
Реализация базовых операций Set
function isSuperset(set, subset) {
for (const elem of subset) {
if (!set.has(elem)) {
return false;
}
}
return true;
}
function union(setA, setB) {
const _union = new Set(setA);
for (const elem of setB) {
_union.add(elem);
}
return _union;
}
function intersection(setA, setB) {
const _intersection = new Set();
for (const elem of setB) {
if (setA.has(elem)) {
_intersection.add(elem);
}
}
return _intersection;
}
function symmetricDifference(setA, setB) {
const _difference = new Set(setA);
for (const elem of setB) {
if (_difference.has(elem)) {
_difference.delete(elem);
} else {
_difference.add(elem);
}
}
return _difference;
}
function difference(setA, setB) {
const _difference = new Set(setA);
for (const elem of setB) {
_difference.delete(elem);
}
return _difference;
}
// Примеры
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([2, 3]);
const setC = new Set([3, 4, 5, 6]);
isSuperset(setA, setB); // true
union(setA, setC); // Set {1, 2, 3, 4, 5, 6}
intersection(setA, setC); // Set {3, 4}
symmetricDifference(setA, setC); // Set {1, 2, 5, 6}
difference(setA, setC); // Set {1, 2}
Связь с объектами массива
const myArray = ["value1", "value2", "value3"];
// Используйте обычный конструктор Set для преобразования массива в набор
const mySet = new Set(myArray);
mySet.has("value1"); // true
// Используйте синтаксис spread для преобразования набора в массив.
console.log([...mySet]); // Покажет вам точно такой же массив, как и myArray
Удаление повторяющиеся элементов из массива
const numbers = [2, 3, 4, 4, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 5, 32, 3, 4, 5];
console.log([...new Set(numbers)]); // [2, 3, 4, 5, 6, 7, 32]
Связь со строками
// Чувствительность к регистру (коллекция будет содержать "F" и "f")
new Set("Firefox"); // Set(7) [ "F", "i", "r", "e", "f", "o", "x" ]
// Пропуск дубликатов ("f" встречается два раза в строке, но в коллекции будет только один раз)
new Set("firefox"); // Set(6) [ "f", "i", "r", "e", "o", "x" ]
Используйте Set для обеспечения уникальности списка значений
const array = Array.from(document.querySelectorAll("[id]")).map((e) => e.id);
const set = new Set(array);
console.assert(set.size === array.length);
Спецификации
Specification |
---|
ECMAScript Language Specification # sec-set-objects |
Совместимость с браузерами
BCD tables only load in the browser