Index of the biggest value in an array
Finding the index of the largest value in an array is one of those tasks that looks trivial but has a few different shapes — each with its own trade-offs around readability, performance and pitfalls.
TL;DR
- A for-loop works but requires several mutable variables.
- A
reducecan do the job in a single pass, but it isn't very readable. - In practice
years.indexOf(Math.max(...years))is usually the best choice — readable and compact, even though it walks the array three times under the hood.
Finding the index of the biggest value
In the upcoming examples, I'll start from this array of years:
const years = [1941, 1714, 2005, 1998, 1871, 2001, 1700]
How do we get the index of the biggest value in the array?
Option 1: for-loop (a bad option)
A common approach is to reach for a regular for-loop:
let max = years[0]
let maxIndex = 0
for (let i = 1; i < years.length; i++) {
if (years[i] > max) {
maxIndex = i
max = years[i]
}
}
// maxIndex = 2
It works, but the solution leans on multiple mutable variables (max, maxIndex, i) — and i in particular exists only to drive the loop, which is exactly the kind of bookkeeping modern array methods let us skip.
Option 2: reduce (a clever option)
The for-loop pattern can be folded into a single reduce call that walks the array once and carries the running max index in the accumulator:
const maxYearIndex = years.reduce(
(maxIndex, curr, index) => (curr > years[maxIndex] ? index : maxIndex),
0,
)
// maxYearIndex = 2
No more mutable bookkeeping variables, and the array is only iterated once. The downside is that you have to read the callback carefully to understand what's happening — maxIndex is the accumulator, curr and index are the current value and its position, and years[maxIndex] is the current max value.
Option 3: Math.max + indexOf (the best option)
The most readable approach is to first get the max value with Math.max and then look up its position with indexOf:
const maxYearIndex = years.indexOf(Math.max(...years))
// maxYearIndex = 2
The whole thing fits on one line and reads almost like plain English: the index of the max of the years. It's tempting to dismiss it on iteration count alone — the spread builds an argument list, Math.max reads it, and indexOf scans the original array, so the data is effectively walked three times. But for arrays that fit in memory anyway, the difference is negligible. Both Math.max and indexOf are built in and run natively, while the reduce variant calls a JS callback per element, so the apparent "three passes vs. one" advantage rarely shows up in practice.
There's one caveat worth knowing: that spread step has a hard limit. For very large arrays (in the order of 100,000+ elements), ...years can throw a "Maximum call stack size exceeded" error because the runtime can't fit that many arguments on the call stack. In that rare case, the reduce variant from Option 2 is the safer fallback.
Extracting into a helper
For reuse, the one-liner is easy to wrap in a generic helper:
function getMaxIndex(array) {
return array.indexOf(Math.max(...array))
}
const maxYearIndex = getMaxIndex(years)
// maxYearIndex = 2
For an empty array this returns -1 for free: Math.max() with no arguments is -Infinity, and [].indexOf(-Infinity) is -1 — a sensible "no index" sentinel.
There you go — now you know how to find the index of the biggest value in an array!
