find, some & every
Not every array operation produces a new array. Sometimes you just want to locate one element, or answer a yes/no question about the collection: “Is there an admin in this list?” or “Are all the fields valid?”. JavaScript ships a family of search-and-test methods — find, findIndex, findLast, some, every, includes, and indexOf — that short-circuit as soon as they have an answer, making them faster and clearer than filtering everything.
Finding a single element
Array.prototype.find() returns the first element for which a predicate returns truthy, or undefined if nothing matches. Unlike filter, it stops the moment it finds a hit instead of scanning the whole array. The callback receives element, index, and the original array.
const users = [
{ id: 1, name: "Ada", role: "user" },
{ id: 2, name: "Linus", role: "admin" },
{ id: 3, name: "Grace", role: "admin" },
];
const admin = users.find((u) => u.role === "admin");
console.log(admin.name);
const missing = users.find((u) => u.role === "guest");
console.log(missing);
Output:
Linus
undefined
Because find can return undefined, guard the result before using it. Optional chaining and nullish coalescing make this clean:
const role = users.find((u) => u.id === 99)?.role ?? "unknown";
console.log(role);
Output:
unknown
findIndex and findLast
findIndex() works exactly like find but returns the position of the first match (or -1 if none). findLast() and findLastIndex() (ES2023) scan from the end, returning the last matching element or index.
const numbers = [5, 12, 8, 130, 44];
console.log(numbers.findIndex((n) => n > 100)); // first > 100
console.log(numbers.findLast((n) => n < 50)); // last < 50
console.log(numbers.findIndex((n) => n > 999)); // no match
Output:
3
44
-1
Tip: Prefer
findoverfilter(...)[0].findshort-circuits on the first match, whilefilteralways walks the entire array and allocates a new one just to throw most of it away.
Testing the whole array
some() and every() are the quantifiers of the array world. Both take a predicate and return a boolean, and both short-circuit.
some()returnstrueif the predicate is truthy for at least one element — it stops at the first match.every()returnstrueonly if the predicate is truthy for every element — it stops at the first failure.
const scores = [82, 91, 67, 75];
console.log(scores.some((s) => s >= 90)); // is anyone an A?
console.log(scores.every((s) => s >= 60)); // did everyone pass?
console.log(scores.every((s) => s >= 80)); // did everyone get a B+?
Output:
true
true
false
A subtle but important detail: some on an empty array is always false, and every on an empty array is always true (vacuous truth). This matches formal logic but can surprise you when validating user input.
console.log([].some((x) => x > 0)); // no element satisfies it
console.log([].every((x) => x > 0)); // nothing violates it
Output:
false
true
Simple membership: includes and indexOf
When you are searching for a value rather than running a predicate, reach for includes or indexOf instead of writing a callback.
includes() returns a boolean and — crucially — uses the SameValueZero algorithm, so it correctly finds NaN. indexOf() returns the index (or -1) but uses strict ===, so it cannot find NaN.
const fruits = ["apple", "banana", "cherry"];
console.log(fruits.includes("banana")); // true
console.log(fruits.indexOf("cherry")); // 2
console.log(fruits.indexOf("mango")); // -1
const vals = [1, NaN, 3];
console.log(vals.includes(NaN)); // includes finds NaN
console.log(vals.indexOf(NaN)); // indexOf cannot
Output:
true
2
-1
true
-1
Gotcha: All of these methods use value comparison for primitives but reference comparison for objects.
[{ id: 1 }].includes({ id: 1 })isfalsebecause the two object literals are different references. To match by content, usesomewith a predicate:arr.some((o) => o.id === 1).
Choosing the right method
| Method | Returns | Short-circuits | Use when |
|---|---|---|---|
find | First matching element or undefined | Yes | You need the matching object itself |
findIndex | Index of first match or -1 | Yes | You need the position |
findLast | Last matching element or undefined | Yes (from end) | You want the most recent match |
some | Boolean | Yes (on first match) | “Does any element match?” |
every | Boolean | Yes (on first failure) | “Do all elements match?” |
includes | Boolean | Yes | Checking for a known primitive value |
indexOf | Index or -1 | Yes | You need the index of a known value |
filter | New array of all matches | No | You need every matching element |
Best Practices
- Reach for
find/some/everyinstead offilterwhenever you only need one element or a yes/no answer — they stop early. - Always handle the
undefinedthatfindcan return, using optional chaining (?.) and??for safe defaults. - Use
includesoverindexOffor boolean membership checks; it reads better and correctly handlesNaN. - Remember the empty-array rule:
every([])istrueandsome([])isfalse. - Search objects by content with
some/findand a predicate, never withincludes/indexOf, which compare by reference. - Keep predicates pure and free of side effects so the search stays predictable.