Array find, some, every, includes
Short-circuiting array predicates: find, findIndex, some, every, and includes — when to use each and common interview traps.
- javascript
- arrays
- find
- some
- every
You do not need filter when you only care about one match or a yes/no answer. find, some, every, and includes short-circuit: they stop as soon as the answer is known. That is both clearer and cheaper on large lists.
Cheat sheet
| Method | Returns | Stops when |
|---|---|---|
arr.includes(x) |
boolean | first SameValueZero match |
arr.some(fn) |
boolean | first truthy predicate |
arr.every(fn) |
boolean | first falsy predicate |
arr.find(fn) |
element or undefined |
first truthy predicate |
arr.findIndex(fn) |
index or -1 |
first truthy predicate |
arr.findLast(fn) |
element or undefined |
last match (ES2023) |
const users = [
{ id: 1, role: 'user', active: true },
{ id: 2, role: 'admin', active: false },
{ id: 3, role: 'admin', active: true },
];
users.find((u) => u.role === 'admin');
// { id: 2, role: 'admin', active: false }
users.some((u) => u.role === 'admin' && u.active); // true
users.every((u) => u.active); // false
users.includes(users[0]); // true — reference equality for objects
[1, 2, NaN].includes(NaN); // true — SameValueZero
includes vs some vs find
includes— fixed value,SameValueZero(soNaNworks; objects only by reference).some— any condition. “Is there an admin?”find— same condition, but you need the element.every— validation: “all items pass?” Empty array:everyis true,someis false (vacuous truth).
[].every(() => false); // true
[].some(() => true); // false
const ids = [10, 20, 30];
ids.includes(20); // true
ids.some((id) => id > 25); // true
ids.find((id) => id > 25); // 30
ids.findIndex((id) => id > 25); // 2
Sparse arrays and holes
Callbacks skip empty slots. includes treats holes as undefined:
const sparse = ['a', , 'c'];
sparse.some((x) => x === undefined); // false — hole skipped
sparse.includes(undefined); // true — hole counts
Real UI patterns
// permission gate
function canPublish(user) {
return user.permissions.some((p) => p === 'publish' || p === 'admin');
}
// form validation
function allRequiredFilled(fields) {
return fields.every((f) => f.value.trim().length > 0);
}
// pick first error message
function firstError(fields) {
return fields.find((f) => f.error)?.error ?? null;
}
Avoid filter(...)[0] when find is enough — you allocate a whole array for one element.
Footguns
- Object identity:
[{a:1}].includes({a:1})isfalse. Usesomewith a field compare. - Truthy traps in find:
find(x => x)skips0,'',false. Be explicit. - Mutating during iteration — don’t; results are unspecified territory.
indexOfvsincludes: preferincludesfor existence;indexOfwhen you need the index of a primitive (or usefindIndex).
// wrong for “is this user in the list?”
selectedUsers.includes(currentUserFromApi); // new object each fetch
// right
selectedUsers.some((u) => u.id === currentUserFromApi.id);
Interview answer
“includes checks value presence with SameValueZero. some/every are boolean predicates with short-circuiting; empty arrays make every true and some false. find/findIndex return the first match or undefined/-1. I use find instead of filter-then-[0], and some with a key compare for objects instead of includes.”
Related
Further reading
Related guides
- Array map, filter, reducemap, filter, and reduce as the core transform toolkit — immutability, chaining costs, reduce patterns, and when a plain loop is clearer.
- Destructuring Objects and ArraysObject and array destructuring — renames, defaults, nested patterns, rest, and parameter destructuring in real APIs.
- Functional Array PatternsPractical functional array techniques — flatMap, partitioning, indexing, zip, and when chaining hurts performance.
- AbortControllerCancel fetch and other async work with AbortController and AbortSignal — timeouts, race conditions, and cleanup when components unmount.
- Arrow Functions Deep DiveLexical this, no arguments object, no construct, concise bodies — when arrows help and when methods and generators need classic functions.