JavaScript60 min total · 16 parts
JavaScript Array and Object Methods Cheat Sheet
Part 4 of 16 · ~3 min
Searching and Testing Arrays
| Method | Finds | On no match | Try it on candidates |
|---|---|---|---|
.find() | first element that passes a test | undefined | candidates.find(c => c.role === "backend") → Priya |
.findIndex() | index of the first match | -1 | candidates.findIndex(c => c.status === "withdrawn") → 1 |
.findLast() | last matching element, search starts from the back | undefined | candidates.findLast(c => c.status === "active") → Sam |
.findLastIndex() | index of the last match | -1 | candidates.findLastIndex(c => c.status === "active") → 3 |
.at(index) | element at that position; negative counts from the end | undefined | candidates.at(-1) → Lena |
.indexOf(value) | position of the first element matching by strict equality | -1 | candidates.map(c => c.id).indexOf("c3") → 2 |
.includes(value) | whether a value shows up anywhere in the array | — | candidates.map(c => c.role).includes("frontend") → true |
.some() | does at least one element satisfy the test | — | candidates.some(c => c.status === "rejected") → true |
.every() | do all of the elements satisfy the test | — | candidates.every(c => c.score > 50) → true |
.findLast() and .findLastIndex() are the newer, search-from-the-end siblings of .find()/.findIndex() — genuinely useful the moment "the most recent match" and "the first match" are different answers, which they are here: the first active candidate is Priya, the last one is Sam.
.at() is worth a specific callout because of what it fixes: candidates[candidates.length - 1] is the classic way to grab the last element, and candidates.at(-1) says the same thing without the arithmetic. It works identically to bracket access for positive indices, and only starts earning its keep with negative ones.
.includes() and .indexOf() look interchangeable and mostly are, except for one specific value. Say a legacy import script chokes on a malformed row and produces a NaN instead of a real score:
const importedScores = [82, NaN, 91, 68, 59]; // row 2 failed to parse
importedScores.includes(NaN); // true
importedScores.indexOf(NaN); // -1 — even though it's right there at index 1
.indexOf() checks internally with ===, and NaN happens to be the one JavaScript value that isn't even equal to itself under strict equality — so no matter how many NaNs sit in an array, .indexOf() will never report finding one. .includes() runs on a different comparison, SameValueZero, which was built specifically to treat two NaNs as a match. Whenever "is this value in here" might involve a NaN, .includes() is the one giving you a truthful answer.
The empty-array behavior of .some()/.every() reads backwards until you think it through. .some() on nothing comes back false — there's nothing present to satisfy the test. .every() on that same nothing comes back true, because a claim about zero items has nothing around to contradict it. The second one is the practical trap: a gate built on .every() will wave an empty candidate list straight through as if every check passed, which is almost never the behavior anyone actually wanted.