Searching Arrays
JavaScript has several methods for finding elements in arrays. Which one you use depends on what you need to know: the element itself, its position, or just whether it is there.
find: Get the First Matching Element
The find method returns the first element that satisfies the test function, or undefined if none is found:
const numbers = [1, 5, 10, 15, 20];
const firstOver10 = numbers.find((n) => n > 10);
console.log(firstOver10); // 15
const over100 = numbers.find((n) => n > 100);
console.log(over100); // undefined
This is particularly useful for finding objects by a property:
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
];
const user = users.find((u) => u.id === 2);
console.log(user); // { id: 2, name: 'Bob' }
const missing = users.find((u) => u.id === 99);
console.log(missing); // undefined
findIndex: Get the Position
The findIndex method returns the index of the first matching element, or -1 if none is found:
const numbers = [1, 5, 10, 15, 20];
const index = numbers.findIndex((n) => n > 10);
console.log(index); // 3
const missingIndex = numbers.findIndex((n) => n > 100);
console.log(missingIndex); // -1
Use findIndex when you need to know where the element is, perhaps to modify or remove it:
const tasks = [
{ id: 1, title: "Buy groceries", done: false },
{ id: 2, title: "Walk dog", done: true },
{ id: 3, title: "Read book", done: false },
];
const indexToUpdate = tasks.findIndex((t) => t.id === 2);
if (indexToUpdate !== -1) {
tasks[indexToUpdate].done = false;
}
includes: Check for Existence
The includes method returns true if an array contains a specific value:
const fruits = ["apple", "banana", "orange"];
console.log(fruits.includes("banana")); // true
console.log(fruits.includes("grape")); // false
It uses SameValueZero comparison, which is like strict equality (===) except that NaN equals NaN. This makes includes reliable for checking NaN:
const numbers = [1, 2, 3, NaN];
console.log(numbers.includes(2)); // true
console.log(numbers.includes(NaN)); // true (SameValueZero handles NaN)
// Compare with indexOf, which uses === and can't find NaN:
console.log(numbers.indexOf(NaN)); // -1
// But with objects, neither method finds different references:
const users = [{ id: 1 }, { id: 2 }];
console.log(users.includes({ id: 1 })); // false (different object reference)
indexOf: Get Position of a Value
The indexOf method returns the index of a value, or -1 if not found:
const colors = ["red", "green", "blue", "green"];
console.log(colors.indexOf("green")); // 1 (first occurrence)
console.log(colors.indexOf("yellow")); // -1
You can specify a starting index:
const colors = ["red", "green", "blue", "green"];
console.log(colors.indexOf("green", 2)); // 3 (search from index 2)
Choosing the Right Method
| Method | Takes | Comparison | Returns |
|---|---|---|---|
find |
A callback | Your custom logic | The element or undefined |
findIndex |
A callback | Your custom logic | Index or -1 |
includes |
A value | SameValueZero | true or false |
indexOf |
A value | Strict equality | Index or -1 |
const items = [
{ id: 1, name: "Widget" },
{ id: 2, name: "Gadget" },
];
// Finding objects - use find/findIndex
const gadget = items.find((item) => item.name === "Gadget");
// Checking primitives - use includes
const tags = ["featured", "sale", "new"];
if (tags.includes("sale")) {
console.log("Item is on sale!");
}
findLast and findLastIndex
ES2023 added methods to search from the end:
const numbers = [1, 5, 10, 15, 20];
const lastOver5 = numbers.findLast((n) => n > 5);
console.log(lastOver5); // 20
const lastIndex = numbers.findLastIndex((n) => n > 5);
console.log(lastIndex); // 4