Array.prototype.indexOf()
Returns the first index at which a value is found, or -1 if it is absent.
indexOf(searchElement)
indexOf(searchElement, fromIndex)- Added in JavaScript ES5 (2009)
Parameters
| Parameter | Type | Description |
|---|---|---|
$searchElement | any | The value to locate, compared using strict equality (===). |
$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, -1 is returned without searching. |
Return value
numberThe first index at which searchElement is found, or -1 if it is not present.
indexOf() scans forward from fromIndex and returns the position of the first element strictly equal to searchElement, or -1. It compares with ===: no type coercion, and object elements match only by reference.
When to reach for it
Use it when you need the index of a primitive — to splice() it out, to overwrite it, or to slice around it. If all you want is a yes/no answer, includes() reads better and avoids the sentinel. If you need to match on a property rather than a value, use findIndex().
What trips people up
NaN is unfindable. Strict equality says NaN !== NaN, so [NaN].indexOf(NaN) is -1 even though the value is right there. includes() or findIndex(Number.isNaN) will find it.
-1 is truthy, so if (arr.indexOf(x)) is wrong in both directions — it is falsy for a hit at index 0 and truthy for a miss. Always write !== -1.
Empty slots in sparse arrays are skipped entirely, so [1, , 3].indexOf(undefined) is -1 while includes(undefined) is true.
Example
When to use it
- Get the position of a value so you can splice it out
- Collect every occurrence of a value by looping with fromIndex
- Deduplicate an array by keeping only first occurrences
- Find where a delimiter first appears in a token list
Frequently asked questions
Why does indexOf() return -1 for a value I can see in the array?
Three usual causes: the value is NaN, which strict equality can never match; the types differ, such as '2' versus 2; or the element is an object and you passed a structurally identical but different object. Use includes(), normalise the type, or use findIndex() with a predicate.
Should I use indexOf() or includes() to check existence?
Use includes() — it returns a boolean, so there is no -1 to forget, and it correctly finds NaN. Keep indexOf() for when you actually need the position.
How do I find all indexes of a value, not just the first?
Loop with the fromIndex argument, restarting at pos + 1 until indexOf returns -1. Alternatively use reduce() or flatMap() with the index argument to collect matching positions in one pass.
More examples
Collecting every occurrence with fromIndex
Prints [0, 2, 3]. Each pass restarts the search one slot past the previous hit; the loop ends when indexOf returns -1. Forgetting the + 1 would find index 0 forever.
const seq = [4, 9, 4, 4, 1];
const hits = [];
let pos = seq.indexOf(4);
while (pos !== -1) {
hits.push(pos);
pos = seq.indexOf(4, pos + 1);
}
console.log(hits);Strict equality, NaN and sparse holes
Prints -1; then -1 and true; then -1 and true. The string '2' is not coerced to a number, NaN never equals itself under ===, and indexOf skips the empty slot that includes() reports as undefined.
console.log([1, 2, 3].indexOf("2"));
console.log([NaN].indexOf(NaN), [NaN].includes(NaN));
console.log([1, , 3].indexOf(undefined), [1, , 3].includes(undefined));
Discussion