Array.prototype.lastIndexOf()
The mirror of indexOf, and it inherits every one of its quirks: strict equality, no coercion, -1 for absent, and NaN can never be found.
Common call
items.lastIndexOf(value)
Returns
number — the last index, or -1
Replaces
a reversed scan with manual index arithmetic
Watch out
the search runs backwards; the index does not
array.lastIndexOf(searchElement[, fromIndex])
→ number
Demo
Live evaluation
Try:
Inputs
itemsnumber[]numbers, comma separated
valuenumbervalue to locate
Output
[1, 2, 1].lastIndexOf(1)
2
With duplicates you get the LAST one — in [1, 2, 1] searching for 1 gives index 2, where indexOf would give 0. Only the scan direction changes: the number returned is still an ordinary left-counted index you can use directly. Absent values give -1, exactly as with indexOf, and the same truthiness trap applies.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| searchElement | any | yes | Value to locate, compared with strict equality (===). |
| fromIndex | number | no (length - 1) | Index to start searching BACKWARDS from. Negative counts from the end. |
Return value
number — Index of the LAST strictly-equal element, or -1. The index still counts from the left.
Common patterns
Find the most recent occurrence
Where the array is append-ordered, the last match is the newest.
const i = events.lastIndexOf(marker);
Walk matches backwards
fromIndex moves the search window left.
let i = items.lastIndexOf(v); while (i !== -1) { found.push(i); i = items.lastIndexOf(v, i - 1); }
Prefer findLastIndex for predicates
lastIndexOf only compares values.
items.findLastIndex(x => x.ok);
Examples
1. Last of two
[1, 2, 1].lastIndexOf(1)
Returns
22. indexOf differs
[1, 2, 1].indexOf(1)
Returns
03. Absent
[1, 2, 3].lastIndexOf(99)
Returns
-14. NaN never found
[NaN].lastIndexOf(NaN)
Returns
-15. includes can
[NaN].includes(NaN)
Returns
true6. Empty array
[].lastIndexOf(1)
Returns
-1Pitfalls
1. -1 is truthy
Identical to indexOf. Testing the result directly is inverted: absent gives -1 which passes an if, and a match at index 0 gives 0 which fails.
Backwards
if (items.lastIndexOf(x)) { ... }
true when ABSENT
Compare explicitly
if (items.lastIndexOf(x) !== -1) { ... }
correct
2. It can never find NaN
Strict equality again — NaN is not equal to itself, so no value-based search can match it. There is no lastIncludes, so you need findLastIndex with Number.isNaN.
Not found
[NaN].lastIndexOf(NaN)
-1
Use a predicate
[NaN].findLastIndex(Number.isNaN)
0
3. fromIndex counts from the left
Even though the scan runs right-to-left, fromIndex is an ordinary index — it is where the search STARTS, and everything to its right is ignored.
Not a count
[1, 2, 1].lastIndexOf(1, 1)
0 // searched indices 0..1 only
Full search
[1, 2, 1].lastIndexOf(1)
2
When to use
Use it
- Finding the most recent occurrence in an append-ordered array
- Walking duplicate matches from the end backwards
Reach for something else
- You need a predicate → findLastIndex
- The value might be NaN → findLastIndex with Number.isNaN
- You want the FIRST match → indexOf
- You only need presence → includes
Notes
Complexity
O(n) — a linear scan from the right, stopping at the first match
Return
A number; -1 means absent, and -1 is truthy
CPython impl
V8: Builtins-array-lastindexof.tq
Memory
No allocation
Thread-safe
Single-threaded; the source is only read
FAQ
No. includes has no reverse counterpart, because a membership test does not depend on direction. If you need NaN handling from the end, use findLastIndex with Number.isNaN.
items.findLastIndex(Number.isNaN)
History
ES5
lastIndexOf standardised in 2009 alongside indexOf.
ES2023
findLast and findLastIndex added, covering predicate-based searching from the end.