I don't think the array that has 5 elements is good case to check time complexity.

So based on @Shidersz's snippet, I made a new one that has many elements and invoked once.

Is Set.has() really O(1) ?

Yes. Time complexity of Set.has() is O(1) according to result of the test below.

const MAX = 10000000
let a = []
a.length = MAX

for (let i = 0; i < MAX; i++) {
  a[i] = i
}

let s = new Set(a)

let o = a.reduce((acc, e) => {
  acc[e] = e
  return acc
}, {})

console.time("Test_Array.IndexOf(0)\t")
a.indexOf(0);
console.timeEnd("Test_Array.IndexOf(0)\t")
console.time("Test_Array.IndexOf(n/2)\t")
a.indexOf(MAX / 2);
console.timeEnd("Test_Array.IndexOf(n/2)\t")
console.time("Test_Array.IndexOf(n)\t")
a.indexOf(MAX);
console.timeEnd("Test_Array.IndexOf(n)\t")

console.time("Test_Set.Has(0)\t\t")
s.has(0)
console.timeEnd("Test_Set.Has(0)\t\t")
console.time("Test_Set.Has(n/2)\t")
s.has(MAX / 2)
console.timeEnd("Test_Set.Has(n/2)\t")
console.time("Test_Set.Has(n)\t\t")
s.has(MAX)
console.timeEnd("Test_Set.Has(n)\t\t")

console.time("Test_Object[0]\t\t")
o[0]
console.timeEnd("Test_Object[0]\t\t")
console.time("Test_Object[n/2]\t")
o[MAX / 2]
console.timeEnd("Test_Object[n/2]\t")
console.time("Test_Object[n]\t\t")
o[MAX]
console.timeEnd("Test_Object[n]\t\t")
.as-console {
  background-color: black !important;
  color: lime;
}

.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

Answer from zmag on Stack Overflow
Top answer
1 of 2
22

I don't think the array that has 5 elements is good case to check time complexity.

So based on @Shidersz's snippet, I made a new one that has many elements and invoked once.

Is Set.has() really O(1) ?

Yes. Time complexity of Set.has() is O(1) according to result of the test below.

const MAX = 10000000
let a = []
a.length = MAX

for (let i = 0; i < MAX; i++) {
  a[i] = i
}

let s = new Set(a)

let o = a.reduce((acc, e) => {
  acc[e] = e
  return acc
}, {})

console.time("Test_Array.IndexOf(0)\t")
a.indexOf(0);
console.timeEnd("Test_Array.IndexOf(0)\t")
console.time("Test_Array.IndexOf(n/2)\t")
a.indexOf(MAX / 2);
console.timeEnd("Test_Array.IndexOf(n/2)\t")
console.time("Test_Array.IndexOf(n)\t")
a.indexOf(MAX);
console.timeEnd("Test_Array.IndexOf(n)\t")

console.time("Test_Set.Has(0)\t\t")
s.has(0)
console.timeEnd("Test_Set.Has(0)\t\t")
console.time("Test_Set.Has(n/2)\t")
s.has(MAX / 2)
console.timeEnd("Test_Set.Has(n/2)\t")
console.time("Test_Set.Has(n)\t\t")
s.has(MAX)
console.timeEnd("Test_Set.Has(n)\t\t")

console.time("Test_Object[0]\t\t")
o[0]
console.timeEnd("Test_Object[0]\t\t")
console.time("Test_Object[n/2]\t")
o[MAX / 2]
console.timeEnd("Test_Object[n/2]\t")
console.time("Test_Object[n]\t\t")
o[MAX]
console.timeEnd("Test_Object[n]\t\t")
.as-console {
  background-color: black !important;
  color: lime;
}

.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

2 of 2
19

If one read the specification of has(), there is an algorithm describing it:

Algorithm for Set.prototype.has(value):

The following steps are taken:

  • Let S be the this value.
  • If Type(S) is not Object, throw a TypeError exception.
  • If S does not have a [[SetData]] internal slot, throw a TypeError exception.
  • Let entries be the List that is the value of S’s [[SetData]] internal slot.
  • Repeat for each e that is an element of entries,
    • If e is not empty and SameValueZero(e, value) is true, return true.
  • Return false.

And apparently, based on that algorithm and the presence of the word REPEAT one can have some confusion about it to be O(1) (we could think it could be O(n)). However, on the specification we can read that:

Set objects must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements in the collection.

Thanks to @CertainPerformance for pointing this.

So, we can create a test to compare Array.indexOf() and Set.has() in the worst case, i.e. look for an item that isn't in the array at all (thanks to @aquinas for pointing this test):

// Initialize array.
let a = [];

for (let i = 1; i < 500; i++)
{
    a.push(i);
}

// Initialize set.
let s = new Set(a);

// Initialize object.
let o = {};
a.forEach(x => o[x] = true);

// Test Array.indexOf().
console.time("Test_Array.indexOf()");
for (let i = 0; i <= 10000000; i++)
{
    a.indexOf(1000);
}
console.timeEnd("Test_Array.indexOf()");

// Test Set.has().
console.time("Test_Set.has()");
for (let i = 0; i <= 10000000; i++)
{
    s.has(1000);
}
console.timeEnd("Test_Set.has()");

// Test Object.hasOwnProperty().
console.time("Test_Object.hasOwnProperty()");
for (let i = 0; i <= 10000000; i++)
{
    o.hasOwnProperty(1000);
}
console.timeEnd("Test_Object.hasOwnProperty()");
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

And now we can see that Set.has() performs better than Array.indexOf(). There is also an extra comparison to Object.hasOwnProperty() to take as reference.

Conclusion:

While O(1) complexity isn't guaranteed, the specification requires the method to run in sublinear time. And Set.has(), generally, will perform better than Array.indexOf().

Another Test:

On next example, we going to generate a random set of sample data and use it later to compare the differents methods.

// Generate a sample array of random items.

const getRandom = (min, max) =>
{
    return Math.floor(Math.random() * (max - min) + min);
}

let sample = Array.from({length: 10000000}, () => getRandom(0, 1000));

// Initialize array, set and object.

let a = [];

for (let i = 1; i <= 500; i++)
{
    a.push(i);
}

let s = new Set(a);
let o = {};
a.forEach(x => o[x] = true);

// Test Array.indexOf().

console.time("Test_Array.indexOf()");
for (let i = 0; i < sample.length; i++)
{
    a.indexOf(sample[i]);
}
console.timeEnd("Test_Array.indexOf()");

// Test Set.has().
console.time("Test_Set.has()");
for (let i = 0; i < sample.length; i++)
{
    s.has(sample[i]);
}
console.timeEnd("Test_Set.has()");

// Test Object.hasOwnProperty().
console.time("Test_Object.hasOwnProperty()");
for (let i = 0; i < sample.length; i++)
{
    o.hasOwnProperty(sample[i]);
}
console.timeEnd("Test_Object.hasOwnProperty()");
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Finally I want to apologize for the confusion the first version of my answer could cause. Thanks to all for giving me a better understanding of my mistakes.

🌐
Reddit
reddit.com › r/learnjavascript › time and space complexity of set()?
r/learnjavascript on Reddit: Time and space complexity of Set()?
April 30, 2021 -

Hi all,

Given:

var containsDuplicate = function(numsArray) {
    return new Set(numsArray).size < nnumsArrayums.length;

};

By declaring Set() would the time complexity be O(n) because javascript would iterate throughout the whole numsArray before adding it to the set?

I'm assuming the space complexity is O(n) because we are adding values (the values in numsArray) to Set().

If we are not adding values, such as the example below, the space complexity would be O(1)

var containsDuplicate = function(numsArray) {
 let a = new Set(); //space complexity of O(1)
 let b = [] //space complexity of O(1)
 return a;
};
Discussions

Javascript ES6 computational/time complexity of collections - Stack Overflow
What time complexity (in big-O notation) is provided by the ES6 specification for the Keyed Collections (Set, Map, WeakSet, and WeakMap)? My expectation, and I expect that of most developers, is that the specifications and implementations would use widely accepted performant algorithms, in which case Set.prototype.has... More on stackoverflow.com
🌐 stackoverflow.com
javascript - What is the Time Complexity of creating set from array? - Stack Overflow
In fact, from the MDN doc page .../docs/Web/JavaScript/Reference/… "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 ... More on stackoverflow.com
🌐 stackoverflow.com
javascript - Time complexity of array.prototype.includes vs. set.prototype.has - Stack Overflow
I've been reading conflicting answers ... engines' time complexity when it comes to sets vs arrays in javascript. I completed the demo task of codility, which is a simple assignment to find a solution for the following: given an array A of N integers, return the smallest positive integer (greater than 0) that does not occur in A. For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5. ... Now, the weird thing is that codility says this solution has a time complexity ... More on stackoverflow.com
🌐 stackoverflow.com
Time and space complexity of Set()?
O(n) new Set([n]) set.keys() set.values() set.entries() set.forEach() O(1) set.add(v) set.delete(v) set.has(v) Not sure: set.clear() More on reddit.com
🌐 r/learnjavascript
4
8
April 30, 2021
🌐
CodeSignal
codesignal.com › learn › courses › mastering-algorithms-map-set-and-two-pointers-in-javascript › lessons › complexity-analysis-and-optimization-with-javascript-sets
Complexity Analysis and Optimization with JavaScript Sets
Since efficiency is a concern in our previous approach, we want to reduce the time complexity by minimizing the number of operations we perform to reach a solution. The JavaScript Set comes to our rescue here. Set internally uses hash tables, which allow operations like insertion, removal, and search to be performed in average constant time, i.e., O(1).
Top answer
1 of 3
93

Right from that very paragraph your linked to:

Set objects must be implemented using [mechanisms] that, on average, provide access times that are sublinear on the number of elements in the collection.

You will find the same sentence for Maps, WeakMaps and WeakSets.

It looks the ECMA spec mandates that the implementations (e.g. Set.prototype.has) are to use a linear time (O(n)) algorithm.

No:

The data structures used in this Set objects specification is only intended to describe the required observable semantics of Set objects. It is not intended to be a viable implementation model.

The observable semantics are mostly related to the predictable iteration order (which still can be implemented efficient and fast). It is indeed expected by the specification that an implementation uses a hash table or something similar with constant access, though trees (with logarithmic access complexity) are allowed as well.

2 of 3
58

For anyone who is curious, I did a very quick benchmark:

I'm running node 18.16.0.

This has been edited to include data on strings and deletion as users have pointed out there is a performance difference. However, object is still faster in everything I ran.

const benchmarkMap = size => {
    console.time('benchmarkMap');
    var map = new Map();
    for (var i = 0; i < size; i++) map.set(i, i);
    for (var i = 0; i < size; i++) var x = map.get(i);
    console.timeEnd('benchmarkMap');
}

const benchmarkObj = size => {
    console.time('benchmarkObj');
    var obj = {};
    for (var i = 0; i < size; i++) obj[i] = i;
    for (var i = 0; i < size; i++) var x = obj[i];
    console.timeEnd('benchmarkObj');
}

const benchmarkMapStr = size => {
    console.time('benchmarkMapStr');
    var map = new Map();
    for (var i = 0; i < size; i++) map.set(i.toString(), i);
    for (var i = 0; i < size; i++) var x = map.get(i.toString());
    console.timeEnd('benchmarkMapStr');
}

const benchmarkObjStr = size => {
    console.time('benchmarkObjStr');
    var obj = {};
    for (var i = 0; i < size; i++) obj[i.toString()] = i;
    for (var i = 0; i < size; i++) var x = obj[i.toString()];
    console.timeEnd('benchmarkObjStr');
}

const benchmarkMapDel = size => {
    console.time('benchmarkMapDel');
    var map = new Map();
    for (var i = 0; i < size; i++) map.set(i, i);
    for (var i = 0; i < size; i++) {
        var x = map.get(i);
        map.delete(i);
    }
    console.timeEnd('benchmarkMapDel');
}

const benchmarkObjDel = size => {
    console.time('benchmarkObjDel');
    var obj = {};
    for (var i = 0; i < size; i++) obj[i] = i;
    for (var i = 0; i < size; i++) {
        var x = obj[i];
        delete obj[i];
    }
    console.timeEnd('benchmarkObjDel');
}

var size = 1000000;

benchmarkMap(size);
benchmarkObj(size);
benchmarkMapStr(size);
benchmarkObjStr(size);
benchmarkMapDel(size);
benchmarkObjDel(size);

This will yield the following results:

benchmarkMap: 189.425ms
benchmarkObj: 41.519ms
benchmarkMapStr: 263.951ms
benchmarkObjStr: 102.959ms
benchmarkMapDel: 271.904ms
benchmarkObjDel: 102.373ms
🌐
Medium
frontendinterviewquestions.medium.com › time-complexity-of-javascript-set-method-47da8a2df769
Time complexity of JavaScript set method | by Pravin M | Medium
October 13, 2024 - In JavaScript, the Set object is a powerful built-in data structure that allows you to store unique values of any type, whether primitive or object references. The Set object offers methods for adding, removing, and checking the existence of values, among other operations. One of the most common operations is the set.add() method, which adds an element to a Set. To effectively utilize Set, it's essential to understand its time complexity and how it impacts the performance of your code.
🌐
DEV Community
dev.to › programminginblood › why-sethas-is-faster-than-arrayincludes-for-finding-items-4hh
Why Set.has() is Faster Than Array.includes() for Finding Items - DEV Community
November 1, 2024 - Set.has() relies on a hash table-based structure that allows for constant-time lookup, or O(1) time complexity. Unlike arrays, set is built for handling unique values, so it won't have duplicate values inside of it and has more lookup times.
🌐
GeeksforGeeks
geeksforgeeks.org › javascript › internal-working-of-set-in-javascript
Internal Working of Set in JavaScript - GeeksforGeeks
July 27, 2026 - Sets in JavaScript internally use Hash Table which means the operations like search, insert and delete work in constant or O(1) time on average and all the stored items are unique.
🌐
Bret Cameron
bretcameron.com › blog › how-to-make-your-code-faster-using-javascript-sets
How to make your code faster using JavaScript Sets | Bret Cameron | Bret Cameron
March 30, 2019 - By contrast, the methods used by Sets to search for, delete and insert items all have a time complexity of just O(1) — that means the size of the data has virtually no bearing on the run-time of these methods!
Find elsewhere
🌐
Medium
medium.com › @conboys111 › what-are-the-time-complexities-of-javascript-set-operations-and-why-do-they-matter-db3f72d797e0
What Are the Time Complexities of JavaScript Set Operations and Why Do They Matter? | by myHotTake | Medium
November 8, 2024 - This has() operation is super fast because JavaScript doesn’t need to search through each item in the Set. It instantly knows whether the robot is there, just like my zoo system would. Again, this operation runs in O(1) time.
🌐
LeetCode
leetcode.com › problems › check-if-n-and-its-double-exist › solutions › 791983 › JavaScript-Hash-Table-or-Set-Space-Time-Complexity-Analysis
[JavaScript] Hash Table or Set - Space Time Complexity ...
August 30, 2020 - Can you solve this real interview question? Check If N and Its Double Exist - Given an array arr of integers, check if there exist two indices i and j such that : * i != j * 0
🌐
DEV Community
dev.to › abdulghaffar349 › optimizing-javascript-collections-comparing-sets-and-arrays-e07
Optimizing JavaScript Collections: Comparing Sets and Arrays - DEV Community
February 28, 2023 - Both sets and arrays have a time complexity of O(1) for adding elements to the end of the collection. However, when it comes to inserting or deleting elements from the middle of the collection, arrays can be slower because they require shifting ...
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › Set
Set - JavaScript - MDN Web Docs
August 13, 2026 - 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).
🌐
Medium
bretcameron.medium.com › how-to-make-your-code-faster-using-javascript-sets-b432457a4a77
How to make your code faster using JavaScript Sets | by Bret Cameron | Medium
April 9, 2019 - In this article, we’ll talk about how JavaScript’s Sets can make your code faster — especially as it scales. There is a significant amount of crossover between what an array can do and what a Set can do. But using Sets will often bring runtime benefits that are impossible to achieve with arrays.
🌐
Adrian Mejia
adrianmejia.com › data-structures-time-complexity-for-beginners-arrays-hashmaps-linked-lists-stacks-queues-tutorial
Data Structures in JavaScript: Arrays, HashMaps, and Lists | Adrian Mejia Blog
December 15, 2020 - HashMap Time Complexities · Sets are very similar to arrays. The difference is that they don’t allow duplicates. How can we implement a Set (Array without duplicates)? We could use an array and check if an element is there before inserting a new one. But the running time of checking if a value is already there is O(n). Can we do better than that? We develop the Map with an amortized run time of O(1)! We could use the JavaScript built-in Set.
🌐
xjavascript
xjavascript.com › blog › javascript-es6-computational-time-complexity-of-collections
JavaScript ES6 Keyed Collections: Time Complexity (Big-O) of Set, Map, WeakSet & WeakMap – What the ES6 Specification Mandates
The ES6 spec focuses on average-case time complexity for core operations, as worst-case scenarios (e.g., hash collisions) are rare with modern implementations. A Set is a collection of unique values (primitives or objects).
Top answer
1 of 3
6

I know this is an old question, but I was double checking the data. I too assumed Set.has would be O(1) or O(log N), but in my first test, it appeared to be O(N). The specs for these functions hint as much, but are quite hard to decipher: https://tc39.es/ecma262/#sec-array.prototype.includes https://tc39.es/ecma262/#sec-set.prototype.has Elsewhere, though, they also say that Set.has must be sublinear-- and I believe modern implementations are.

Empirically, Set.has demonstrates linear performance when I ran it in some code playgrounds... but in real environments like node and chrome, they there were no surprises. I'm not sure what the playground was running on the back end, but perhaps a Set polyfill was used. So be careful!

Here's my test cases, trimmed down to remove the randomness:

const makeArray = (size) => [...Array(size)].map(() => size);

const small =  makeArray(1000000);
const medium = makeArray(10000000);
const large =  makeArray(100000000);

const solution1 = arr => {
  console.time('Array.includes');
  arr.includes(arr.length - 1)
  console.timeEnd('Array.includes');
}

const solution2 = arr => {
  const set = new Set(arr)
  console.time('Set.has');
  set.has(arr.length-1)
  console.timeEnd('Set.has');
}


console.log('** Testing small array:');
solution1(small);
solution2(small);
console.log('** Testing medium array:');
solution1(medium);
solution2(medium);
console.log('** Testing large array:');
solution1(large);
solution2(large);

In Chrome, though:

** Testing small array:
VM183:10 Array.includes: 1.371826171875 ms
VM183:17 Set.has: 0.005859375 ms
VM183:25 ** Testing medium array:
VM183:10 Array.includes: 14.32568359375 ms
VM183:17 Set.has: 0.009765625 ms
VM183:28 ** Testing large array:
VM183:10 Array.includes: 115.695068359375 ms
VM183:17 Set.has: 0.0048828125 ms

In Node 16.5:

Testing small array:
Array.includes: 1.223ms
Set.has: 0.01ms
Testing medium array:
Array.includes: 11.41ms
Set.has: 0.054ms
Testing large array:
Array.includes: 127.297ms
Set.has: 0.047ms

So, yeah, Arrays are definitionly linear, and Sets are much faster.

2 of 3
2

The comparison like that is not entirely fair because in the function where you use the Set, the Array needs to be converted to a Set first, which takes some time.

Have a look at the results below if this is ignored. I have updated the solution2 function to receive a Set and changed the while loop to a for loop - for the sake of direct comparison.

You may notice that for a small array, Set might be slower. This is trivial because the time complexity only really comes into affect for a large (significant) n.

Also note, Array.includes is indeed O(n) but because it is in a for loop which in the worst case could go up to n the solution has a time complexity of O(n^2).

const rand = (size) => [...Array(size)].map(() => Math.floor(Math.random() * size));

const small = rand(100);
const medium = rand(5000);
const large = rand(100000);

const solution1 = arr => {
  console.time('Array.includes');
  for (let int = 1;;int++) {
    if (!arr.includes(int)) {
      console.timeEnd('Array.includes');
      return int;
    }
  }
}

const solution2 = set => {
  console.time('Set.has');
  for (let i = 1;;i++) {
    if (!set.has(i)) {
      console.timeEnd('Set.has');
      return i
    }
  }
}

console.log('Testing small array:');
solution1(small);
solution2(new Set(small));
console.log('Testing medium array:');
solution1(medium);
solution2(new Set(medium));
console.log('Testing large array:');
solution1(large);
solution2(new Set(large));
Run code snippetEdit code snippet Hide Results Copy to answer Expand

🌐
Timveletta
timveletta.com › blog › array-set-object-map
Array vs Set vs Object vs Map - Tim Veletta
August 18, 2023 - However, if we want to find an ID within the Array, we would have to iterate over the Array using find or findIndex, resulting in a time complexity of O(n). If we want to know if the Array contains a certain ID value, we can use the includes function, which also iterates through all the items of the Array. For Sets, we only have access to the has function, which produces the same result as the includes function in Arrays.
🌐
Medium
medium.com › @inbasekaran18 › understanding-time-complexity-of-array-methods-in-javascript-cc7bb30b3e9d
Understanding Time Complexity of Array Methods in JavaScript | by Inbasekaran | Medium
May 29, 2024 - ```javascript let arr = new Set([1, 2, 3, 4, 5]); for (let i = 0; i < arr.size; i++) { if (arr.has(i)) { // Do something } } ``` By converting the array to a `Set`, we reduce the lookup complexity to O(1), leading to an overall complexity of O(n). ...