配列の最大値・最小値を求める

Math.max() にスプレッドで渡すのがいちばん短い書き方です。空配列で -Infinity になること、 null が 0 に化けること、件数が多いと落ちること、最大の要素そのものを取る方法まで確かめます。

実行して検証済み処理系Node 22.23.3対応ES2015難易度●●○○○目安 約7分更新

答え

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
4 1
javascript
console.log(Math.max(...[]));
console.log(Math.min(...[]));
-Infinity Infinity

Math.max() は配列を受け取らないので、... で1つずつに開いて渡します。 → スプレッド構文と残余

ただし、そのまま使うと3つの穴があります。

穴1: 空の配列で -Infinity になる

javascript
const prices = [];
const highest = Math.max(...prices);

console.log(`最高額は ${highest} 円`);
最高額は -Infinity 円
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
4 null

引数が1つも無いときの決まりです。エラーにはなりません。

これがそのまま画面に出たり、次の計算に混ざったりします。

javascript
console.log(Math.max(...[1, null, 3]));
console.log(Math.max(...[1, undefined, 3]));
console.log(Math.max(...['3', '10']));
console.log(Math.max(...[1, NaN, 3]));
3 NaN 10 NaN
javascript
console.log(Math.max(...[null, -5]));
console.log(Math.min(...[null, 5]));
0 0

先に確かめてください。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
3
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
4 1

null を返すか、既定値を返すか、投げるかは仕様しだいです。決めずに -Infinity のまま流さない、というのがここでの要点です。

穴2: 数値でないものが混ざる

javascript
try {
[].reduce((a, b) => (a > b ? a : b));
} catch (error) {
console.log(error.name + ': ' + error.message);
}
TypeError: Reduce of empty array with no initial value
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
300
  • null は0 として扱われます
  • undefined と NaN は全体を NaN にします
  • 文字列は数値に変換されるので、'3' と '10' は正しく比べられます

undefined と NaN は NaN になるので気づけます。 null だけが静かに通り、答えを変えます。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{ name: 'a', price: 300 }
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{ name: 'a', price: 300 } { name: 'a', price: 300 }

どちらにも 0 は入っていません。

→ なぜ == ではなく === を使うのか

穴3: 件数が多いと落ちる

... は要素を関数の引数として渡します。 引数を積む場所には限りがあるので、件数が多いと RangeError になります。

実測すると、検証に使っている Node 22.23.3 では 10万件は通り、13万件で Maximum call stack size exceeded になりました。 この境目は処理系と版で変わります。 数を覚えないでください。

件数が読めないときは reduce() を使ってください。

reduce() は初期値を書かないと、空配列で落ちます。

落ちるのは、黙って -Infinity を返すよりましです。 どちらの形でも、空のときにどうするかは自分で決めてください。

最大の「要素」が欲しいとき

値ではなく、その要素そのものが欲しいことのほうが多いはずです。

これではどれが 300 円だったのか分かりません。

1回のループで要素が取れます。

並べ替えても取れますが、要らない仕事が増えます。

toSorted() は元の配列を変えないので、items はそのままです。 sort() を使うと元が並び替わります。 → 配列を数値の大きさで並び替える

使い分け

欲しいもの 件数が少ない 件数が多い・不明
最大値 Math.max(...list) list.reduce(...)
最大の要素 list.reduce(...) list.reduce(...)
上位いくつか toSorted().slice(0, n) toSorted().slice(0, n)

まとめ

  • 短いのは Math.max(...list)。ただし空配列で -Infinity
  • null は 0 に化ける。undefined と NaN は全体を NaN にする
  • 件数が多いと RangeError。 境目は環境しだい。読めないなら reduce()
  • reduce() は初期値なしだと空配列で落ちる。どちらでも空の扱いは自分で決める
  • 要素そのものが欲しいなら reduce() で持ち回る

この記事の根拠

  1. Math.max — ECMAScript® 2026 Language Specificationtc39.es
  2. Array.prototype.reduce — ECMAScript® 2026 Language Specificationtc39.es

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)