Published
Node.js Performance: Array.includes vs Set.has
What is the fastest way to see if an array has a value?
When you want to find out if an array contains a value, what tools do you reach for?
There is Array.includes()
and Set.has()
. So which one is better? Let’s dive in
and find out!
Table of contents
- The Different Ways to Combine Arrays
- Note About Arrays vs Sets
- Testing Methodology
- The Test Machine
- Results
- Conclusions
- So, what is the best way to see if an array has a value in JavaScript?
- Feedback
The Different Ways to Combine Arrays
Array.include()
const included = arr.include(value);
This is pretty straightforward, you have an array of values. You want to know if a specific value is contained in that array. Couldn’t be more simple.
Set.has()
const included = set.has(value);
Similar to Array.includes()
, Set.has()
lets you test if a set contains a certain
value.
Creating a set from an array
const set = new Set(arr);
const included = set.has(value);
So, what if you already have an array, but have heard great things about the performance
of Set.has()
? You’ll have to create a new set from the array using new Set(arr)
.
Note About Arrays vs Sets
It is important to note how arrays and sets differ. Technical details aside, the biggest difference between an array and a set is that sets only allow unique data in them. By contrast, an array allows duplicate values. It depends on your use case when developing which one you want to use.
Testing Methodology
As with my previous benchmarking of loops and array combining, I used the Tinybench library. The benchmarks use sets and arrays in different variations to check if they contain a value. The value used in the test isn’t in the arrays so we can test the worst-case scenario, when the whole array needs to be scanned to find the value. This test was run against different array lengths to see if one method or another was more effective at different sizes.
The tests also use different run times to compare performance across engines. Currently, the engines included are:
- Node.js v18
- Node.js v20
- Node.js v22
- Bun v1.3.18
- Deno v2.1.4
You can see the full test suite over at my GitHub Repo.
Browsers weren’t considered for this test as I’m mainly focusing on server-side JavaScript engines.
The Test Machine
The machine I’m running these tests on is a System76 Darter Pro 8. It has a 12th-generation Intel CPU that clocks in around 4.70 GHz (model i7-1260P). And it has 32 GB of RAM.
Results
Here are the results combining two arrays with lengths of ten, one thousand, ten thousand, and one hundred thousand.
Conclusions
Set.has()
has way better performance than Array.includes()
. However, that’s not
the whole story. The Set.has()
test doesn’t include creating a set from an array.
That benchmark reflects the case when you already have a set created.
But if you create a set from an array you need to consider the performance impact of creating the set from the array values. But once you have the set created, well then you can have crazy fast lookup times if you need to query the set multiple times.
If you need to look up values in an array multiple times, you take a performance
hit each time you need to scan the array. So you may be tempted to convert it to
a set and use Set.has()
. However, that’s not always your best option unless you
are doing a lot of Set.has()
calls.
An interesting outcome from this benchmark shows that Node v22 may not have as good
performance with Array.includes()
as v18 and v20 have. This is at larger array
lengths as smaller arrays v22 seems to have a better time with than v18 and v20.
Another interesting observation is that Node v20 seems to perform extremely well
with Array.includes()
at large array compared to everything else. This could just
be a fluke or a flaw in my testing.
So, what is the best way to see if an array has a value in JavaScript?
The answer is… it depends! As with everything in programming, the best tool for the
job depends a lot on context. If you have an array and don’t need to do many calls
to Array.includes()
you can just use Array.includes()
. If you already have a set
just use Set.has()
.
However, if you have an array and want to convert it to a set to use Set.has()
you probably shouldn’t. Unless that array is very large and you need to do a large
number of lookups on the array, it is probably not worth the cost to initialize
the set.
However, (again) if you know you need to do lookups on an array and you can create
a set instead of creating an array, then you might want to consider doing that to
reap the faster lookup times of Set.has()
.
Feedback
If you have any feedback on my testing methodologies or suggestions for improvement, just create an issue on my GitLab repo for this blog or on the GitLab repo for the benchmarks.