Array.prototype.indexOf()
indexOf(searchElement, fromIndex) indexOf() searches an array starting at index 0 and moving forward, returning the first index where the given element is found. Returns -1 when the element is not found. This is one of the original array search methods from ES1 and remains widely used because it returns the position - which includes() does not.
For checking simple existence, prefer includes(). For finding elements by a computed condition, use findIndex(). Use indexOf() when you specifically need the numeric position of a value in the array.
Syntax
indexOf(searchElement)
indexOf(searchElement, fromIndex)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
searchElement | any | - | The value to search for in the array |
fromIndex | number | 0 | The index to start searching from |
Examples
Basic usage
const fruits = ["apple", "banana", "orange", "banana", "melon"];
console.log(fruits.indexOf("banana"));
// 1
console.log(fruits.indexOf("grape"));
// -1
The fromIndex parameter lets you skip past the start of the array, which is useful when you already know the element you want is not in the first few positions. It also makes it possible to find the next occurrence after a previously found index.
Using fromIndex
const letters = ["a", "b", "c", "b", "a"];
// Start searching from index 2
console.log(letters.indexOf("b", 2));
// 3
Once you understand fromIndex, you can chain multiple indexOf calls together to collect every position where a value appears, not just the first one. The loop below repeatedly updates fromIndex to skip past the last-found position, building up a list of all matching indices.
Finding all occurrences
const numbers = [1, 2, 3, 2, 1, 2, 3];
const target = 2;
const indices = [];
let index = numbers.indexOf(target);
while (index !== -1) {
indices.push(index);
index = numbers.indexOf(target, index + 1);
}
console.log(indices);
// [1, 3, 5]
The examples above cover the fundamental mechanics. In practice, indexOf sits inside common patterns that appear frequently in real code — existence checks, conditional removal, and position-based logic. Each pattern relies on the -1 sentinel that indexOf uses to signal absence.
Common Patterns
Checking if an element exists
const users = ["alice", "bob", "charlie"];
if (users.indexOf("bob") !== -1) {
console.log("User found");
}
// User found
// Or simply
const exists = users.includes("bob");
console.log(exists);
// true
Checking existence tells you whether an element is present, but sometimes you need to act on that information—for instance, removing the first instance of a value from the array itself. The splice method paired with indexOf makes this a clean one-pass operation.
Removing specific occurrences
const items = ["a", "b", "c", "b", "d"];
const toRemove = "b";
const idx = items.indexOf(toRemove);
if (idx !== -1) {
items.splice(idx, 1);
}
console.log(items);
// ['a', 'c', 'b', 'd']
The examples so far all work with primitives like strings and numbers. When arrays hold objects, indexOf behaves differently because it compares references, not content. Understanding this distinction prevents subtle bugs where you expect a value-based match but get -1 instead.
Strict equality
indexOf uses strict equality (===) for comparison. Objects are compared by reference, not by value.
const objects = [{ id: 1 }, { id: 2 }];
const found = objects.indexOf({ id: 1 });
console.log(found);
// -1 - different object reference
// To find by property, use findIndex()
const foundByProp = objects.findIndex(obj => obj.id === 1);
console.log(foundByProp);
// 0
indexOf cannot find NaN because NaN !== NaN. Use findIndex(x => Number.isNaN(x)) or includes(NaN) for that case.
Negative fromIndex
When fromIndex is negative, the search starts at array.length + fromIndex. If the resulting start position is less than 0, the whole array is searched from the beginning. The returned index is always relative to the start of the array, regardless of fromIndex.
const arr = ['a', 'b', 'c', 'b', 'a'];
// -1 starts from index 4 (last element)
console.log(arr.indexOf('b', -1)); // -1 (not found at index 4+)
// -3 starts from index 2
console.log(arr.indexOf('b', -3)); // 3
Performance
indexOf() performs a linear scan from fromIndex to the end of the array. For very large arrays where you search repeatedly, consider converting to a Set for O(1) lookups, or precomputing an index map. For small arrays - which cover most real-world use cases - the linear scan is fast enough that the overhead of building a Set would outweigh any gain.
When using fromIndex to find the next occurrence in a loop, each call restarts from the given position rather than scanning the whole array, so the total work across all calls is still O(n) rather than O(n²).
indexOf() vs includes() vs findIndex()
Choose the right method for the job:
indexOf(value)- need the position; searching for a primitive or known referenceincludes(value)- just need a boolean; also correctly handlesNaNfindIndex(fn)- need the position; matching by property or complex condition
For most existence checks in modern code, includes is preferable because it reads as plain English and avoids the !== -1 comparison.
See Also
- Array.prototype.includes() - check if array contains an element
- Array.prototype.findIndex() - find index using a predicate function
- Array.prototype.find() - find the element itself