JavaScript Array includes() method checks whether an array contains a particular value and returns true or false. It is useful for clear membership checks, such as confirming that a selected option, permission, or label is present. Unlike indexOf(), it can find NaN. The sections below add practical examples for object arrays, conditional searches, value matching, and sparse arrays.
Syntax and Formal Specification
The method signature is includes(searchElement, fromIndex).
const numbers = [1, 2, 3, 4, 5]; console.log(numbers.includes(3)); // true console.log(numbers.includes(3, 3)); // false (search starts at index 3) console.log(numbers.includes(3, -3)); // true (starts at index 2)
Parameters
searchElement— The value to search for. Compared viaSameValueZero, which treatsNaNas equal to itself and treats+0and-0as equal.fromIndex(optional) — The index at which to start searching. Defaults to0. Negative values are treated as offsets from the end (-1is the last element). IffromIndex >= length, the search starts beyond the array and immediately returnsfalse. If negative and beyond-length, the search starts from index0.
Return Value
A boolean: true if a matching element is found within the search range, false otherwise.
console.log([].includes(1)); // false (empty array) console.log([undefined].includes()); // true (undefined is present) console.log([1, 2].includes()); // false (undefined not present)
Generic Usage on Array-Like Objects
Because the method is generic, it can be applied to arguments, DOM collections, and custom objects with length:
const arrayLike = { 0: "a", 1: "b", 2: "c", length: 3 }; const found = Array.prototype.includes.call(arrayLike, "b"); console.log(found); // true function findInArgs(value) { return Array.prototype.includes.call(arguments, value); } console.log(findInArgs("x")); // false
Strings have their own includes() method (String.prototype.includes), which performs a substring search rather than an element comparison. Do not conflate the two.
Performance: Linear Search and Comparison with indexOf()
includes() runs in O(n) time for an array of n elements. It short-circuits at the first match, so its effective cost depends on how early the target appears. In the worst case (target at the end or absent), it visits every element.
const big = new Array(1_000_000).fill(0); const start = performance.now(); big.includes(0); // Match at index 0, near-instant console.log(performance.now() - start); const start2 = performance.now(); big.includes(-1); // Full scan, ~O(n) console.log(performance.now() - start2);
includes() vs indexOf() !== -1
For pure existence checks, includes() is the preferred idiom. Both return the same result for primitive values (except for NaN), and modern engines optimize includes() to be at least as fast as indexOf() !== -1, often marginally faster because it avoids producing a sentinel -1 that must be compared. The primary advantages of includes() are:
- Readability:
arr.includes(x)is a direct expression of “does this array include x?” - Correctness for
NaN:arr.indexOf(NaN) !== -1is alwaysfalseeven ifNaNis present. - Boolean return type: No need to add
!== -1at the call site.
const values = [1, 2, NaN, 3]; console.log(values.indexOf(NaN) !== -1); // false (BUG!) console.log(values.includes(NaN)); // true (correct)
Array includes() vs String includes()
Both methods share the name but differ in semantics. Array includes() compares elements by SameValueZero; String includes() searches for a substring.
console.log(["hello"].includes("hello")); // true (whole string element) console.log("hello world".includes("hello")); // true (substring) console.log(["hello world"].includes("hello")); // false (not whole element)
The fromIndex Optimization
When the target is known to appear late, a positive fromIndex can skip a prefix and reduce scanning:
const arr = new Array(1_000_000).fill(0); arr[999_999] = -1; // Full scan: near-instant (match at index 0) arr.includes(0); // Skipped prefix: efficient arr.includes(-1, 500_000);
A negative fromIndex is an offset from the end, then the search proceeds forward. For example, -1 starts at the last item and checks only that position; earlier items will not be searched.
const arr = [1, 2, 3, 4, 5]; console.log(arr.includes(5, -1)); // true (starts at index 4) console.log(arr.includes(1, -1)); // false (starts at index 4) console.log(arr.includes(1, -100)); // true (clamped to 0)
Check values with the expected type and spelling
includes() compares a complete array element with the value you pass; it does not convert one type into another or perform a partial text search. For strings, the comparison is case-sensitive. Use the same data type and spelling that the array stores.
const values = [1, "1", "JavaScript"];
console.log(values.includes(1)); // true
console.log(values.includes("1")); // true
console.log(values.includes("01")); // false
console.log(values.includes("javascript")); // false
In the first two checks, the values match different elements: the number 1 and the string “1” are not interchangeable. For a case-insensitive text check, normalize both the search value and array values, or use a callback method such as some().
Using includes() with objects
For objects, includes() checks whether the exact same object reference is in the array. It does not compare object properties. Two separate objects with identical fields are still different references.
const firstUser = { id: 7, name: "Asha" };
const users = [firstUser];
console.log(users.includes(firstUser)); // true
console.log(users.includes({ id: 7, name: "Asha" })); // false
const hasUserId = users.some(user => user.id === 7);
console.log(hasUserId); // true
If the goal is to match by an ID, name, or another property, some() is usually the right choice for a yes-or-no result. Use find() when you need the matching object, or findIndex() when you need its position.
Use some() for a condition instead of an exact value
includes() accepts a value to compare, not a predicate function. Passing a function does not make it test each item; it simply looks for that function object as an array element. For conditions such as “is any score over 90?” or “does any task remain incomplete?”, use some().
const scores = [72, 84, 93];
console.log(scores.includes(score => score > 90)); // false
console.log(scores.some(score => score > 90)); // true
The first call searches for the callback function itself, which is not stored in scores. The second call runs the condition for each score and stops when it finds a match. For a single known value, includes() stays simpler and more direct.
includes() and sparse array holes
includes() treats an empty slot, or hole, in a sparse array like undefined for its search. This is different from indexOf(), which skips empty slots. If your application distinguishes an unassigned position from a position that explicitly stores undefined, test whether the index is an own property as well.
const sparse = new Array(3);
const explicitUndefined = [undefined];
console.log(sparse.includes(undefined)); // true
console.log(sparse.indexOf(undefined)); // -1
console.log(explicitUndefined.includes(undefined)); // true
Most arrays used in everyday application code are dense, so every index has a value. The distinction matters when arrays are created with a length and populated only at selected positions, or when code deletes array elements with the delete operator.
Use the Boolean result in a condition
Because includes() already returns a Boolean, you can use it directly in an if statement. This reads naturally for lists of supported roles, selected filters, or required features.
const enabledFeatures = ["search", "export", "darkMode"];
if (enabledFeatures.includes("export")) {
console.log("Export is available");
}
If you need to display every missing required value, combine membership checks with filter() rather than stopping at the first result:
const required = ["search", "export", "backup"];
const missing = required.filter(feature => !enabledFeatures.includes(feature));
console.log(missing); // ["backup"]
This pattern is clear for short lists. For very large lists with many repeated membership checks, convert the values to a Set once and use set.has(value) for each lookup.
