Includes, contains or has. Finding things in iterables (lists) in JavaScript
Tags: javascript
Published: 2021-01-29 16:18:46

When writing JavaScript, very frequently I need to check if a given <em>thing</em> exists in a <em>list of things</em>. Every single time I need to look up the function that does that for the sort of list I'm working with. 

You see, there are three possible options: <code>includes()</code>, <code>contains()</code> and <code>has()</code> and I mix them up all the time. So I'm writing this for my own reference.

<h3>The main problem</h3>
Checking if a given thing is in a list is a common action in JavaScript (for me at least). For example, I do it when I need to check if a specific class is applied to an element, or if a return value of a function matches one of multiple values. 

The function name to use for this depends on the type of list you're working with, even though the <em>signature</em> of each function is exactly the same. 

You call a function on the list with the item as an argument and you end up with a boolean that tells you if the item is in the list or not:

```js
// returns true or false
list.function(item);
```

<h4>Arrays: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes">includes()</a></h4>

For arrays, you need to use the <code>includes()</code> function.

<h4>classList: <a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/contains">contains()</a></h4>

classList is a <code>DOMTokenList</code>, and those use <code>contains()</code>.

<h4>Map: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has">has()</a></h4>

Maps (and WeakMaps) are relatively new features and act as a sort of "better" object (I won't go into the differences in this article). 

To figure out if a given <strong>key</strong> exits in a Map, you need to use <code>has()</code>.

<h4>Set: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has">has()</a></h4>

Sets (and WeakSets) are relatively new features and act as a sort of "better" array (Again, I won't go into the differences in this article). 

For Sets you also need to use <code>has()</code>.

<h4>In handy table form:</h4>

<table>
<thead>
<tr>
<td></td>
<th>Function to use</th></tr>
</thead>
<tbody>
<tr><th>Array</th><td><code>.includes()</code></td></tr>
<tr><th>classList</th><td><code>.contains()</code></td></tr>
<tr><th>Map</th><td><code>.has()</code></td></tr>
<tr><th>Set</th><td><code>.has()</code></td></tr>
</tbody>
</table>


<h3>Why is it not all the same?</h3>
Honestly I don't know.

We can split JavaScript into two parts: language features and DOM APIs. Both of these are made/designed by different groups of people: language features by ECMA and DOM APIs essentially by browser vendors. 

classList is a DOM api whereas Array, Set and Map are all language features, which could explain the difference between classList and the rest.

It still doesn't explain why Array uses <code>includes</code> and Sets and Maps use <code>has</code>. I can't think of a good reason other than oversight during API development, but maybe someone can tell me.

In any case I hope that having written this down will help me remember better, or that it will at least be a quick lookup for me.