Array.prototype.includes()
Determines whether an array contains a given value, returning true or false.
includes(searchElement)
includes(searchElement, fromIndex)- Added in JavaScript ES2016
Parameters
| Parameter | Type | Description |
|---|---|---|
$searchElement | any | The value to search for, compared using the SameValueZero algorithm. |
$fromIndexoptional | integer= 0 | Zero-based index to start searching at, converted to an integer. A negative value counts back from the end (fromIndex + array.length); below -array.length it is treated as 0. If it is at least array.length the array is not searched and false is returned. |
Return value
booleantrue if searchElement is found within the array (or within the portion starting at fromIndex), otherwise false.
includes() is the readable membership test: it returns a boolean, so there is no -1 sentinel to remember. Prefer it over indexOf(x) !== -1 whenever you only care whether the value is present.
SameValueZero, not ===
Comparison uses SameValueZero, which behaves like === with exactly one difference: NaN equals itself. (It also treats +0 and -0 as equal, but so does === — that is where SameValueZero differs from Object.is(), not from ===.) The NaN difference is the whole reason to prefer it for numeric data — [NaN].includes(NaN) is true while indexOf() can never find NaN.
What trips people up
It is still an identity check for objects. [{id: 1}].includes({id: 1}) is false, because those are two different objects. Use find() or some() with a predicate to match on contents.
There is no type coercion either: ["1"].includes(1) is false. Normalise types before searching mixed data.
Finally, a negative fromIndex shifts the start of the search but does not reverse it — the array is always scanned front to back from that computed offset.
Example
When to use it
- Check whether a user's role list contains a required permission
- Test whether a file extension is on an allow-list
- Detect NaN in a numeric column, which indexOf() cannot do
- Guard against re-adding a value that is already in a list
Frequently asked questions
What is the difference between includes() and indexOf()?
includes() returns a boolean and finds NaN; indexOf() returns a position and uses strict equality, so it can never locate NaN. Use includes() for a yes/no test and indexOf() when you need the index.
Why does includes() return false for an object that looks identical?
Because it compares references, not structure. Two object literals with the same properties are distinct values — use arr.some(o => o.id === target.id) to match on contents.
Is includes() case-sensitive for strings?
Yes — string elements are compared exactly, so ['Admin'].includes('admin') is false. Normalise the case first with map(s => s.toLowerCase()), or use some() with a case-insensitive comparison.
More examples
How fromIndex behaves
Prints false, true, true, false. Starting at index 1 skips past the only 'a'. -1 resolves to index 2 and still scans forward, finding 'c'. A fromIndex below -length is clamped to 0, so the whole array is searched; one past the end short-circuits to false.
const letters = ["a", "b", "c"];
console.log(letters.includes("a", 1));
console.log(letters.includes("c", -1));
console.log(letters.includes("a", -100));
console.log(letters.includes("c", 5));Reference identity and no coercion
Prints false, true, true, false, true. A fresh object literal is never the same reference, so some() with a predicate is the right tool for structural matching. The string '1' does not match the number 1, and SameValueZero treats -0 and 0 as equal.
const objs = [{ id: 1 }];
console.log(objs.includes({ id: 1 }));
console.log(objs.includes(objs[0]));
console.log(objs.some((o) => o.id === 1));
console.log(["1", "2"].includes(1));
console.log([-0].includes(0));
Discussion