Array.prototype.findLast()

The backwards halves of find and findIndex. Before ES2023 the idiom was to reverse a copy and correct the index by hand, which is exactly the arithmetic these remove.

Array methodsES2023Live demo
Common call
items.findLast(x => x.ok)
Returns
the element (findLast) or its index (findLastIndex)
Replaces
[...items].reverse().find(...) plus index arithmetic
Watch out
the index is still counted from the LEFT
array.findLast(callback) | array.findLastIndex(callback)
→ any | number

Demo

Live evaluation
Try:
Inputs
itemsnumber[]numbers, comma separated
thresholdnumberfind the last below this
methodstringfindLast or findLastIndex
Output
[1, 2, 3, 4]['findLast'](x => x < 3)
2

Both walk the array from the END towards the start and stop at the first element that passes. In [1, 2, 3, 4] the last element below 3 is the 2 at index 1 — so findLast gives 2 and findLastIndex gives 1. Note that the index is still measured from the left; only the scan direction reversed. The two no-match cases show the different failure values: undefined for the element form, -1 for the index form.

Parameters

NameTypeRequiredDescription
callbackFunctionyesCalled as callback(element, index, array), starting at the last element and working backwards. Iteration stops at the first truthy result.
thisArganyno (undefined)Value of `this` inside the callback. Ignored for arrow functions.

Return value

any | number — findLast returns the last matching ELEMENT, or undefined. findLastIndex returns its POSITION, or -1. Everything else about them is identical.

Common patterns

Most recent matching entry
In an append-ordered log, the last match is the newest.
const latest = events.findLast(e => e.type === "error");
Trim from the end
The index of the last real element bounds a slice.
const end = items.findLastIndex(x => x != null);
const trimmed = items.slice(0, end + 1);
The pre-2023 idiom
What these replaced — note the index arithmetic.
const i = items.length - 1 - [...items].reverse().findIndex(pred);

Examples

1. Last matching element
[1, 2, 3, 4].findLast(x => x < 3)
Returns
2
2. Its index
[1, 2, 3, 4].findLastIndex(x => x < 3)
Returns
1
3. find goes forwards
[1, 2, 3, 4].find(x => x < 3)
Returns
1
4. No match, element
[1, 2, 3].findLast(x => x > 99)
Returns
undefined
5. No match, index
[1, 2, 3].findLastIndex(x => x > 99)
Returns
-1
6. Empty array
[].findLast(x => true)
Returns
undefined

Pitfalls

1. The index still counts from the left
Only the scan direction reversed. findLastIndex does not return a distance from the end, so the result slots straight into normal indexing — which is right, but not what "last" suggests to everyone.
Not from the end
[1, 2, 3, 4].findLastIndex(x => x < 3)
1 // not 2
Convert if needed
items.length - 1 - items.findLastIndex(pred)
distance from the end
2. findLast cannot distinguish a falsy match
Exactly the same trap as find. A matched 0 and a failed search both look falsy, so truthiness testing the result is unsafe whenever the array can hold falsy values.
Zero looks missing
const n = [0, 1].findLast(x => x === 0);
if (!n) { /* "not found" */ }
wrongly takes the not-found branch
Use findLastIndex
if (items.findLastIndex(pred) !== -1) { ... }
unambiguous
3. ES2023 and newer only
These are recent. Older runtimes need the reverse-a-copy idiom, and reversing in place would mutate the source — the copy is not optional.
Missing method
items.findLast(pred)
TypeError: items.findLast is not a function
Old idiom
[...items].reverse().find(pred)
the element

When to use

Use it
  • The most recent entry in an append-ordered array
  • Trimming or bounding from the end
  • Any search where the last match matters rather than the first
Reach for something else
  • You want the FIRST match → find or findIndex
  • You are matching a plain value → lastIndexOf
  • Runtimes older than ES2023 → reverse a copy

Notes

Complexity
O(n) worst case; stops at the first match from the end
Return
The element or undefined (findLast); the index or -1 (findLastIndex)
CPython impl
V8: Builtins-array-findlast.tq
Memory
No allocation — unlike the reverse-a-copy idiom they replaced
Thread-safe
Single-threaded; mutating the source inside the callback is undefined behaviour

FAQ

Because it returns a position, and positions in JavaScript arrays are always left-counted — that is what makes the result usable directly with bracket notation or slice. Only the search order is reversed.

const i = items.findLastIndex(pred);
items[i];   // works directly

History

ES2023
findLast and findLastIndex added, completing the find family in both directions.