Spec-Zone.ru › JavaScript

Set

Baseline Широко доступно

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и в версиях браузеров. Она доступна во всех браузерах с июля 2015 года.

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

Описание

Объекты Set представляют собой коллекции значений. Значение в наборе может встречаться только один раз; оно является уникальным в коллекции набора. Вы можете перебирать элементы набора в порядке их добавления. *Порядок добавления* соответствует порядку, в котором каждый элемент был успешно добавлен в набор методом add() (то есть, идентичный элемент уже отсутствовал в наборе при вызове add()).

Спецификация требует, чтобы наборы были реализованы "обеспечивающими в среднем время доступа, сублинейное от количества элементов в коллекции". Следовательно, он может быть внутренне представлен как хеш-таблица (с поиском O(1)), дерево поиска (с поиском O(log(N))) или любая другая структура данных, при условии, что сложность лучше, чем O(N).

Равенство значений

Равенство значений основано на алгоритме SameValueZero. (Ранее использовался SameValue, который считал 0 и -0 разными. Проверьте совместимость с браузерами.) Это означает, что NaN считается таким же, как NaN (хотя NaN !== NaN), а все остальные значения считаются равными в соответствии с семантикой оператора ===. Кроме того, для ключей объектов равенство основано на идентичности объекта. Они сравниваются по ссылке, а не по значению. См. Использование объекта Set для примеров.

Производительность

Метод has проверяет, находится ли значение в наборе, используя подход, который в среднем быстрее, чем проверка большинства элементов, ранее добавленных в набор. В частности, он в среднем быстрее, чем метод Array.prototype.includes, когда массив имеет length, равный size набора.

Состав наборов

Объект Set предоставляет некоторые методы, позволяющие составлять наборы, как при математических операциях. Эти методы включают:

Метод Тип возвращаемого значения Математический эквивалент Диаграмма Венна
A.difference(B) Set A∖BA\setminus B A Venn diagram where two circles overlap. The difference of A and B is the part of A that is not overlapping B.
A.intersection(B) Set A∩BA\cap B A Venn diagram where two circles overlap. The intersection of A and B is the part where they overlap.
A.symmetricDifference(B) Set (A∖B)∪(B∖A)(A\setminus B)\cup(B\setminus A) A Venn diagram where two circles overlap. The symmetric difference of A and B is the region contained by either circle but not both.
A.union(B) Set A∪BA\cup B A Venn diagram where two circles overlap. The union of A and B is the region contained by either or both circles.
A.isDisjointFrom(B) Boolean A∩B=∅A\cap B = \empty A Venn diagram with two circles. A and B are disjoint because the circles have no region of overlap.
A.isSubsetOf(B) Boolean A⊆BA\subseteq B A Venn diagram with two circles. A is a subset of B because A is completely contained in B.
A.isSupersetOf(B) Boolean A⊇BA\supseteq B A Venn diagram with two circles. A is a superset of B because B is completely contained in A.

Чтобы сделать их более обобщенными, эти методы принимают не только объекты Set, но и все, что похоже на набор.

Объекты, похожие на наборы

Все методы составления наборов требуют, чтобы this был реальным экземпляром Set, но их аргументы должны быть просто похожими на наборы. *Объект, похожий на набор* — это объект, который предоставляет следующее:

  • Свойство size, содержащее число.
  • Метод has(), принимающий элемент и возвращающий булево значение.
  • Метод keys(), возвращающий итератор элементов набора.

Например, объекты Map похожи на наборы, поскольку они также имеют size, has() и keys(), поэтому они ведут себя как наборы ключей при использовании в методах набора:

const a = new Set([1, 2, 3]);
const b = new Map([
  [1, "one"],
  [2, "two"],
  [4, "four"],
]);
console.log(a.union(b)); // Set(4) {1, 2, 3, 4}

Примечание: Протокол "похожий на набор" вызывает метод keys() вместо [Symbol.iterator]() для получения элементов. Это сделано для того, чтобы карты были допустимыми объектами, похожими на наборы, потому что для карт итератор возвращает *записи*, а метод has() принимает *ключи*.

Массивы не похожи на наборы, поскольку у них нет метода has() или свойства size, а их метод keys() возвращает индексы, а не элементы. Объекты WeakSet также не похожи на наборы, потому что у них нет метода keys().

API браузеров, похожие на наборы

Объекты, похожие на Set в браузерах (или "setlike objects") — это интерфейсы Web API, которые во многих отношениях ведут себя как Set.

Как и в Set, элементы можно перебирать в том же порядке, в котором они были добавлены в объект. Объекты, похожие на Set, и Set также имеют свойства и методы с одинаковыми именами и поведением. Однако, в отличие от Set, они разрешают только определенный предопределенный тип для каждой записи.

Разрешенные типы устанавливаются в IDL-определении спецификации. Например, GPUSupportedFeatures — это объект, похожий на Set, который должен использовать строки в качестве ключа/значения. Это определяется в IDL спецификации ниже:

interface GPUSupportedFeatures {
  readonly setlike<DOMString>;
};

Объекты, похожие на Set, являются либо только для чтения, либо для чтения/записи (см. ключевое слово readonly в IDL выше).

  • Объекты, похожие на Set, только для чтения имеют свойство size и методы: entries(), forEach(), has(), keys(), values() и [Symbol.iterator]().
  • Записываемые объекты, похожие на Set, дополнительно имеют методы: clear(), delete() и add().

Методы и свойства имеют то же поведение, что и эквивалентные сущности в Set, за исключением ограничений на типы записей.

Ниже приведены примеры объектов браузера, похожих на Set, только для чтения:

  • GPUSupportedFeatures
  • XRAnchorSet

Ниже приведены примеры записываемых объектов браузера, похожих на Set:

  • CustomStateSet
  • FontFaceSet
  • Highlight
  • ViewTransitionTypeSet

Конструктор

Set()
Создает новый объект Set.

Статические свойства

Set[Symbol.species]
Конструктор, используемый для создания производных объектов.

Свойства экземпляра

Эти свойства определены в Set.prototype и общие для всех экземпляров Set.

Set.prototype.constructor
Конструктор, создавший объект экземпляра. Для экземпляров Set начальное значение — конструктор Set.
Set.prototype.size
Возвращает количество значений в объекте Set.
Set.prototype[Symbol.toStringTag]
Начальное значение свойства [Symbol.toStringTag] — строка "Set". Это свойство используется в Object.prototype.toString().

Методы экземпляра

Set.prototype.add()
Вставляет указанное значение в этот набор, если оно еще не присутствует.
Set.prototype.clear()
Удаляет все элементы из объекта Set.
Set.prototype.delete()
Удаляет указанное значение из этого набора, если оно находится в наборе.
Set.prototype.difference()
Принимает набор и возвращает новый набор, содержащий элементы из этого набора, но отсутствующие в данном наборе.
Set.prototype.entries()
Возвращает новый объект итератора, который содержит массив из [value, value] для каждого элемента в объекте Set, в порядке добавления. Это похоже на объект Map, поэтому *ключ* каждой записи совпадает с ее *значением* для Set.
Set.prototype.forEach()
Вызывает callbackFn один раз для каждого значения, присутствующего в объекте Set, в порядке добавления. Если предоставлен параметр thisArg, он будет использоваться в качестве значения this для каждого вызова callbackFn.
Set.prototype.has()
Возвращает булево значение, указывающее, существует ли указанное значение в этом Set.
Set.prototype.intersection()
Принимает набор и возвращает новый набор, содержащий элементы, присутствующие как в этом, так и в данном наборе.
Set.prototype.isDisjointFrom()
Принимает набор и возвращает булево значение, указывающее, имеет ли этот набор общих элементов с данным набором.
Set.prototype.isSubsetOf()
Принимает набор и возвращает булево значение, указывающее, содержатся ли все элементы этого набора в данном наборе.
Set.prototype.isSupersetOf()
Принимает набор и возвращает булево значение, указывающее, содержатся ли все элементы данного набора в этом наборе.
Set.prototype.keys()
Псевдоним для Set.prototype.values().
Set.prototype.symmetricDifference()
Принимает набор и возвращает новый набор, содержащий элементы, которые присутствуют либо в этом наборе, либо в данном наборе, но не в обоих.
Set.prototype.union()
Принимает набор и возвращает новый набор, содержащий элементы, которые присутствуют либо в этом, либо в обоих наборах.
Set.prototype.values()
Возвращает новый объект итератора, который выдает значения для каждого элемента в объекте Set в порядке добавления.
Set.prototype[Symbol.iterator]()
Возвращает новый объект итератора, который выдает значения для каждого элемента в объекте Set в порядке добавления.

Примеры

Использование объекта 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("some text"); // Set(3) { 1, 5, 'some text' }
const o = { a: 1, b: 2 };
mySet1.add(o);

mySet1.add({ a: 1, b: 2 }); // o is referencing a different object, so this is okay

mySet1.has(1); // true
mySet1.has(3); // false, since 3 has not been added to the set
mySet1.has(5); // true
mySet1.has(Math.sqrt(25)); // true
mySet1.has("Some Text".toLowerCase()); // true
mySet1.has(o); // true

mySet1.size; // 5

mySet1.delete(5); // removes 5 from the set
mySet1.has(5); // false, 5 has been removed

mySet1.size; // 4, since we just removed one value

mySet1.add(5); // Set(5) { 1, 'some text', {...}, {...}, 5 } - a previously deleted item will be added as a new item, it will not retain its original position before deletion

console.log(mySet1); // Set(5) { 1, "some text", {…}, {…}, 5 }

Перебор наборов

Перебор набора посещает элементы в порядке их добавления.

for (const item of mySet1) {
  console.log(item);
}
// 1, "some text", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5

for (const item of mySet1.keys()) {
  console.log(item);
}
// 1, "some text", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5

for (const item of mySet1.values()) {
  console.log(item);
}
// 1, "some text", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5

// key and value are the same here
for (const [key, value] of mySet1.entries()) {
  console.log(key);
}
// 1, "some text", { "a": 1, "b": 2 }, { "a": 1, "b": 2 }, 5

// Convert Set object to an Array object, with Array.from
const myArr = Array.from(mySet1); // [1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}, 5]

// the following will also work if run in an HTML document
mySet1.add(document.body);
mySet1.has(document.querySelector("body")); // true

// converting between Set and Array
const mySet2 = new Set([1, 2, 3, 4]);
console.log(mySet2.size); // 4
console.log([...mySet2]); // [1, 2, 3, 4]

// intersect can be simulated via
const intersection = new Set([...mySet1].filter((x) => mySet2.has(x)));

// difference can be simulated via
const difference = new Set([...mySet1].filter((x) => !mySet2.has(x)));

// Iterate set entries with forEach()
mySet2.forEach((value) => {
  console.log(value);
});
// 1
// 2
// 3
// 4

Реализация базовых операций с наборами

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;
}

// Examples
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); // returns true
union(setA, setC); // returns Set {1, 2, 3, 4, 5, 6}
intersection(setA, setC); // returns Set {3, 4}
symmetricDifference(setA, setC); // returns Set {1, 2, 5, 6}
difference(setA, setC); // returns Set {1, 2}

Связь с массивами

const myArray = ["value1", "value2", "value3"];

// Use the regular Set constructor to transform an Array into a Set
const mySet = new Set(myArray);

mySet.has("value1"); // returns true

// Use the spread syntax to transform a set into an Array.
console.log([...mySet]); // Will show you exactly the same Array as myArray

Удаление дублирующихся элементов из массива

// Use to remove duplicate elements from an array
const numbers = [2, 13, 4, 4, 2, 13, 13, 4, 4, 5, 5, 6, 6, 7, 5, 32, 13, 4, 5];

console.log([...new Set(numbers)]); // [2, 13, 4, 5, 6, 7, 32]

Связь со строками

// Case sensitive (set will contain "F" and "f")
new Set("Firefox"); // Set(7) [ "F", "i", "r", "e", "f", "o", "x" ]

// Duplicate omission ("f" occurs twice in the string but set will contain only one)
new Set("firefox"); // Set(6) [ "f", "i", "r", "e", "o", "x" ]

Использование набора для обеспечения уникальности списка значений

const array = Array.from(document.querySelectorAll("[id]")).map((e) => e.id);

const set = new Set(array);
console.assert(set.size === array.length);

Спецификации

Спецификация
ECMAScript® 2027 Language Specification
# sec-set-objects

Совместимость с браузерами

Настольные Мобильные Сервер
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
Set
38
12
13
25
8
38
14
25
8
3.0
38
8
1.0.0
1.0
0.12.0
@@iterator
43
12
36
27–36A placeholder property named @@iterator is used.
17–27A placeholder property named iterator is used.
30
9
43
36
27–36A placeholder property named @@iterator is used.
17–27A placeholder property named iterator is used.
30
9
4.0
43
9
1.0.0
1.0
0.12.0
@@species
51
13
41
38
10
51
41
41
10
5.0
51
10
1.0.0
1.0
6.5.0
Set
38
12
13
25
8
38
14
25
8
3.0
38
8
1.0.0
1.0
0.12.0
add
38
12
13
25
8
38
14
25
8
3.0
38
8
1.0.0
1.0
0.12.0
clear
38
12
19
25
8
38
19
25
8
3.0
38
8
1.0.0
1.0
0.12.0
delete
38
12
13
25
8
38
14
25
8
3.0
38
8
1.0.0
1.0
0.12.0
difference
122
122
127
108
17
122
127
81
17
26.0
122
17
1.0.0
1.42
22.0.0
entries
38
12
24
25
8
38
24
25
8
3.0
38
8
1.0.0
1.0
0.12.0
forEach
38
12
25
25
8
38
25
25
8
3.0
38
8
1.0.0
1.0
0.12.0
has
38
12
13
25
8
38
14
25
8
3.0
38
8
1.0.0
1.0
0.12.0
intersection
122
122
127
108
17
122
127
81
17
26.0
122
17
1.0.0
1.42
22.0.0
isDisjointFrom
122
122
127
108
17
122
127
81
17
26.0
122
17
1.0.0
1.42
22.0.0
isSubsetOf
122
122
127
108
17
122
127
81
17
26.0
122
17
1.0.0
1.42
22.0.0
isSupersetOf
122
122
127
108
17
122
127
81
17
26.0
122
17
1.0.0
1.42
22.0.0
key_equality_for_zeros
38
12
29
25
9
38
29
25
9
3.0
38
9
1.0.0
1.0
4.0.0
keys
38
12
24
25
8
38
24
25
8
3.0
38
8
1.0.0
1.0
0.12.0
size
38
12
19From Firefox 13 to Firefox 18, the size property was implemented as a Set.prototype.size() method, this has been changed to a property in later versions conform to the ECMAScript 2015 specification.
25
8
38
19From Firefox for Android 14 to Firefox for Android 18, the size property was implemented as a Set.prototype.size() method, this has been changed to a property in later versions conform to the ECMAScript 2015 specification.
25
8
3.0
38
8
1.0.0
1.0
0.12.0
symmetricDifference
122
122
127
108
17
122
127
81
17
26.0
122
17
1.0.0
1.42
22.0.0
union
122
122
127
108
17
122
127
81
17
26.0
122
17
1.0.0
1.42
22.0.0
values
38
12
24
25
8
38
24
25
8
3.0
38
8
1.0.0
1.0
0.12.0

См. также

  • Полифилл Set в core-js
  • es-shims полифилл Set
  • Map
  • WeakMap
  • WeakSet

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API