W3cubDocs

/JavaScript

Set

The Set object lets you store unique values of any type, whether primitive values or object references.

Description

Set objects are collections of values. A value in the Set may only occur once; it is unique in the Set's collection. You can iterate through the elements of a set in insertion order. The insertion order corresponds to the order in which each element was inserted into the set by the add() method successfully (that is, there wasn't an identical element already in the set when add() was called).

The specification requires sets to be implemented "that, on average, provide access times that are sublinear on the number of elements in the collection". Therefore, it could be represented internally as a hash table (with O(1) lookup), a search tree (with O(log(N)) lookup), or any other data structure, as long as the complexity is better than O(N).

Value equality

Value equality is based on the SameValueZero algorithm. (It used to use SameValue, which treated 0 and -0 as different. Check browser compatibility.) This means NaN is considered the same as NaN (even though NaN !== NaN) and all other values are considered equal according to the semantics of the === operator.

Performance

The Set has method checks if a value is in a Set object, using an approach that is, on average, quicker than testing most of the elements that have previously been added to the Set object. In particular, it is, on average, faster than the Array.prototype.includes method when an Array object has a length equal to a Set object's size.

Constructor

Set()

Creates a new Set object.

Static properties

get Set[@@species]

The constructor function that is used to create derived objects.

Instance properties

Set.prototype.size

Returns the number of values in the Set object.

Instance methods

Set.prototype.add()

Inserts a new element with a specified value in to a Set object, if there isn't an element with the same value already in the Set.

Set.prototype.clear()

Removes all elements from the Set object.

Set.prototype.delete()

Removes the element associated to the value and returns a boolean asserting whether an element was successfully removed or not. Set.prototype.has(value) will return false afterwards.

Set.prototype.has()

Returns a boolean asserting whether an element is present with the given value in the Set object or not.

Set.prototype[@@iterator]()

Returns a new iterator object that yields the values for each element in the Set object in insertion order.

Set.prototype.values()

Returns a new iterator object that yields the values for each element in the Set object in insertion order.

Set.prototype.keys()

An alias for Set.prototype.values().

Set.prototype.entries()

Returns a new iterator object that contains [value, value] for each element in the Set object, in insertion order.

This is similar to the Map object, so that each entry's key is the same as its value for a Set.

Set.prototype.forEach()

Calls callbackFn once for each value present in the Set object, in insertion order. If a thisArg parameter is provided, it will be used as the this value for each invocation of callbackFn.

Examples

Using the Set object

const mySet1 = new Set()

mySet1.add(1)           // Set [ 1 ]
mySet1.add(5)           // Set [ 1, 5 ]
mySet1.add(5)           // Set [ 1, 5 ]
mySet1.add('some text') // Set [ 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 [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)
// logs Set(5) [ 1, "some text", {…}, {…}, 5 ] in Firefox
// logs Set(5) { 1, "some text", {…}, {…}, 5 } in Chrome

Iterating Sets

// iterate over items in set
// logs the elements in insertion order: 1, "some text", {"a": 1, "b": 2}, {"a": 1, "b": 2}, 5
for (const item of mySet1) {
  console.log(item);
}

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

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

// logs the elements in insertion order: 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);
}

// 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

Implementing basic set operations

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}

Relation with Array objects

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

Remove duplicate elements from the array

// Use to remove duplicate elements from the array

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]

Relation with Strings

const text = 'India';

const mySet = new Set(text);  // Set(5) {'I', 'n', 'd', 'i', 'a'}
mySet.size  // 5

//case sensitive & duplicate omission
new Set("Firefox")  // Set(7) { "F", "i", "r", "e", "f", "o", "x" }
new Set("firefox")  // Set(6) { "f", "i", "r", "e", "o", "x" }

Use Set to ensure the uniqueness of a list of values

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

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

Specifications

Browser compatibility

Desktop Mobile Server
Chrome Edge Firefox Internet Explorer Opera Safari WebView Android Chrome Android Firefox for Android Opera Android Safari on IOS Samsung Internet Deno Node.js
@@iterator
43
12
36
27-36
A placeholder property named @@iterator is used.
17-27
A placeholder property named iterator is used.
No
30
9
43
43
36
27-36
A placeholder property named @@iterator is used.
17-27
A placeholder property named iterator is used.
30
9
4.0
1.0
0.12.0
@@species
51
13
41
No
38
10
51
51
41
41
10
5.0
1.0
6.5.0
6.0.0
Set
38
12
13
11
25
8
38
38
14
25
8
3.0
1.0
0.12.0
0.10.0
Set
38
12
13
11
25
8
38
38
14
25
8
3.0
1.0
0.12.0
0.10.0
add
38
12
13
11
Returns 'undefined' instead of the 'Set' object.
25
8
38
38
14
25
8
3.0
1.0
0.12.0
0.10.0
clear
38
12
19
11
25
8
38
38
19
25
8
3.0
1.0
0.12.0
delete
38
12
13
11
25
8
38
38
14
25
8
3.0
1.0
0.12.0
0.10.0
entries
38
12
24
No
25
8
38
38
24
25
8
3.0
1.0
0.12.0
forEach
38
12
25
11
25
8
38
38
25
25
8
3.0
1.0
0.12.0
has
38
12
13
11
25
8
38
38
14
25
8
3.0
1.0
0.12.0
0.10.0
key_equality_for_zeros
38
12
29
No
25
9
38
38
29
25
9
3.0
1.0
4.0.0
size
38
12
19
From 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.
11
25
8
38
38
19
From 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
3.0
1.0
0.12.0
values
38
38
12
12
24
24
No
25
25
8
8
38
38
38
38
24
24
25
25
8
8
3.0
3.0
1.0
1.0
0.12.0
0.12.0

See also

© 2005–2022 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