
Array.includes() vs. indexOf() in JavaScript

Before Array.includes() arrived, one of the most common ways to check whether an array contained a value was indexOf().
That pattern worked, but it was never especially elegant:
const hasItem = items.indexOf('tea') !== -1;includes() made the intent much clearer:
const hasItem = items.includes('tea');That difference may look small, but in everyday code it matters. includes() asks the same question your code is really asking. indexOf() asks a more detailed question and then forces you to convert the answer into the thing you actually wanted.
indexOf() returns a position
indexOf() returns the index of the first matching item, or ‑1 if the value is not found.
const items = ['bread', 'milk', 'tea'];console.log(items.indexOf('milk')); // 1console.log(items.indexOf('coffee')); // -1That is useful when you genuinely care about the position in the array.
But many developers have historically used it only as a proxy for containment:
if (items.indexOf('tea') !== -1) { console.log('Tea found');}That works, but it is less direct than asking for containment explicitly.
includes() returns a boolean
includes() does exactly what its name suggests. It tells you whether the array includes the value.
const items = ['bread', 'milk', 'tea'];console.log(items.includes('tea')); // trueconsole.log(items.includes('coffee')); // falseThis makes the method especially good for:
- conditional checks
- validation rules
- membership tests
- readable everyday logic
If your code wants a yes or no answer, includes() is often the better fit.
Readability is the Biggest Everyday Difference
Compare these two:
const isSupported = browsers.indexOf('Safari') !== -1;const isSupported = browsers.includes('Safari');The second version is simply easier to read.
That is not a trivial point. Much of good front‑end code is about choosing constructs that make intent obvious, not merely technically correct.
NaN is one of the important edge cases
This is where the two methods differ in a more interesting way.
indexOf() cannot find NaN properly:
const values = [1, 2, NaN];console.log(values.indexOf(NaN)); // -1That is surprising until you remember that NaN is a special value that does not compare equal to itself with normal equality rules.
includes(), however, can detect NaN:
console.log(values.includes(NaN)); // trueThis is one of the best concrete examples of why includes() is not just prettier syntax laid over the top of indexOf(). The behaviour is not identical.
Use indexOf() when you truly need the index
It would be a mistake to frame this as "always use includes() now".
If you need the position of the value in the array, indexOf() is still a perfectly valid tool.
For example:
const index = items.indexOf('milk');if (index !== -1) { console.log(`Milk is at position ${index}`);}That is a real position‑based use case. includes() cannot replace that because it does not tell you where the item is.
Use includes() when the question is about membership
If the actual question is:
- is this value present?
- does the list contain this item?
- is this selection allowed?
then includes() is usually the better expression of the intent.
That is really the heart of the comparison. One method is about position. The other is about presence.
The Same Idea Shows up with Strings
JavaScript strings also have an includes() method:
const title = 'JavaScript Fundamentals';console.log(title.includes('Script')); // trueThat consistency makes includes() feel quite natural in the language overall. When you want to know whether something contains something else, includes() is often the clearest question to ask.
Older codebases may still lean on indexOf()
You will still see indexOf() !== ‑1 often, especially in older code or code written before includes() became the natural default.
That is not automatically wrong. It just tends to be a bit noisier, and it misses the NaN advantage mentioned earlier.
If you are maintaining that code, the most sensible approach is usually to understand both patterns and use the clearer one when writing or refactoring fresh logic.
A Practical Example
Imagine a form that allows only certain categories:
const allowedCategories = ['books', 'music', 'games'];const selectedCategory = 'music';Using includes():
const isAllowed = allowedCategories.includes(selectedCategory);That reads very naturally.
If you wrote the same with indexOf():
const isAllowed = allowedCategories.indexOf(selectedCategory) !== -1;the logic is still correct, but the extra comparison gets in the way of the actual meaning.
Wrapping up
indexOf() and includes() both help you inspect arrays, but they answer different questions. indexOf() tells you where a value was found, whilst includes() tells you whether the value is present at all. If your code wants a boolean membership check, includes() is usually the clearer and more direct choice, and it also handles NaN more helpfully than indexOf().
Key Takeaways
indexOf()returns an index or‑1.includes()returnstrueorfalse.includes()is usually clearer when your code only cares about presence.indexOf()is still useful when you genuinely need the position of a value.includes()can matchNaN, whereasindexOf()cannot.
Most of the time, the simplest rule is: if you want a boolean, ask for a boolean.
Related Articles

React Portals Explained. 
String.startsWith(), endsWith(), and includes() in JavaScript. String.startsWith(),endsWith(), andincludes()in JavaScript
Array.find(), Array.some(), and Array.every() in JavaScript. Array.find(),Array.some(), andArray.every()in JavaScript
Sort the Keys of an Object with JavaScript. Sort the Keys of an Object with JavaScript

Image Optimisation with next/image. Image Optimisation with
next/image
Optimising Website Performance with HTML, CSS, and JavaScript. Optimising Website Performance with HTML, CSS, and JavaScript

Has Google Killed AMP? Has Google Killed AMP?

React's Reconciliation Algorithm Explained. React's Reconciliation Algorithm Explained

Specificity in CSS. Specificity in CSS

Track Element Visibility Using Intersection Observer. Track Element Visibility Using Intersection Observer

Understanding the Nullish Coalescing (??) Operator in JavaScript. Understanding the Nullish Coalescing (
??) Operator in JavaScript
Simplify Your Layout CSS with place‑items. Simplify Your Layout CSS with
place‑items