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