Use array.includes(value). It returns true or false, compares with strict equality, and (unlike the older indexOf(value) !== -1) finds NaN. For an array of objects, test a property with array.some((item) => item.id === 2).
"Is this value in the array?" has had three answers over JavaScript's life. Old code compares indexOf() against -1. Since ES2016 there is includes(), which says what it means and returns a boolean. And for objects, where both of those compare references rather than contents, some() takes a test function. This page covers all three, then the point where an array is the wrong structure and a Set should take over. Each example runs on this page: hit Run, then edit the code and run it again.
1array.includes()Recommended
includes(value) walks the array and returns true as soon as an element matches, false if none does. The match is strict, like ===, so no type conversion happens: the string '7' is not the number 7. It works on arrays of strings, numbers, booleans and any other primitive, and it is the idiomatic answer in any code written since ES2016.
Output
Prints true, false, 7 is prime, false, then false. The last one is false because the search starts at index 1, after 'apple'. Calling includes() on an empty array is safe and returns false. Don't confuse it with the string method of the same name: 'banana'.includes('nan') checks for a substring.
2indexOf() !== -1 (the older way)
Before includes() existed, the membership test was array.indexOf(value) !== -1. indexOf() returns the position of the first match, or -1 when there is none, so comparing against -1 turns it into a yes/no answer. You will meet it in older code and in answers written before 2016. It behaves like includes() for everyday values, with one real exception: NaN.
Output
Prints 2, -1, found banana, then -1 and true. indexOf() uses ===, and NaN === NaN is false, so it can never find NaN. includes() uses the SameValueZero algorithm, which treats NaN as equal to itself. Keep indexOf() for when you actually need the position; for a yes/no check, includes() is clearer and has no blind spot.
3Arrays of objects and custom tests: some()
includes() and indexOf() compare objects by reference, not by contents. A new object literal that looks identical to an element is a different object, so it is never found. To ask "is there a user with id 2?", pass a test function to some(): it calls the function on each element and returns true at the first one that passes. The same trick covers any comparison === can't express, such as a case-insensitive match.
Output
Prints false, true, false, true, true. some() only answers yes or no. If you need the matching object itself, or its position, use find() or findIndex() with the same test; see find an object in an array by property.
4Which should you use?
| Method | Returns | Finds NaN | Best for |
|---|---|---|---|
| arr.includes(v) | true / false | Yes | Yes/no membership, the default |
| arr.indexOf(v) !== -1 | Index or -1 | No | Older code, or when you need the position |
| arr.some(fn) | true / false | If your test does | Objects by property, custom comparisons |
| set.has(v) | true / false | Yes | Many lookups against the same values |
5Many lookups? Use a Set
Every method above scans the array, so each check costs time proportional to its length. That is fine for a one-off check. It adds up when you test hundreds of values against the same list inside a loop. Build a Set from the array once, and each has() after that is a hash lookup that takes about the same time however big the set is.
Output
Prints mail.com is fine, junk.net is blocked, [ 'bad.org', 'spam.com' ], then true. A Set uses the same SameValueZero equality as includes(), so objects are still matched by reference. For an array of objects, build the set from the property you look up, such as new Set(users.map((u) => u.id)).
6Common variation: contains all or any of several values
To check several values at once, combine includes() with every() (all must be present) or some() (at least one must be). If you already hold Sets, ES2025 added isSubsetOf() and isDisjointFrom(), which answer the same questions directly.
Output
Prints true, false, true, true, true. isDisjointFrom() returns true when the two sets share no values, so "contains none of these" is true and "contains any" is its negation.
Frequently asked questions
What is the difference between includes() and indexOf()?
includes() returns a boolean, while indexOf() returns the position or -1. They also compare differently: includes() uses SameValueZero, so [NaN].includes(NaN) is true, while indexOf() uses === and can never find NaN. They also treat holes in sparse arrays differently: [1, , 3].includes(undefined) is true but [1, , 3].indexOf(undefined) is -1.
Why does includes() return false for an object that is clearly in the array?
Because objects (and arrays) are compared by reference. [[1, 2]].includes([1, 2]) is false: the array literal you pass is a new array, not the one stored inside. Test a property with some() instead, for example users.some((u) => u.id === 2), or keep a reference to the original object and pass that.
How do I check if an array contains a value case-insensitively?
Use some() and normalize both sides: tags.some((t) => t.toLowerCase() === value.toLowerCase()). If you check many values against the same list, build a Set of lower-cased entries once and call has() on the lower-cased value.
Does includes() convert types, so that "2" matches 2?
No. includes() does no type coercion, so [1, 2, 3].includes("2") is false. If your values may arrive as strings (from JSON or a form, say), convert them first, e.g. ids.includes(Number(input)).
Is includes() slow on large arrays?
It is a linear scan, which is fine for a single check on any realistic array. The cost shows when you call it repeatedly against the same array, such as inside a loop over another list. Convert the array to a Set once and use set.has(value), which is a hash lookup.
Can I use includes() everywhere, or do I need indexOf() for older environments?
Array.prototype.includes was added in ES2016 and is supported by every current browser and every maintained Node.js version. You only need indexOf(value) !== -1 for engines from before 2016, such as Internet Explorer.
Run it yourself
Open any of these in the full JavaScript editor: tweak, run, and share.
JavaScript playground