---
type: how-to
language: javascript
slug: array/max-min
title: "配列の最大値・最小値を求める"
title_tag: "JavaScript 配列の最大値 — Math.max と reduce の使い分け"
summary: >
  Math.max() にスプレッドで渡すのがいちばん短い書き方です。空配列で -Infinity になること、
  null が 0 に化けること、件数が多いと落ちること、最大の要素そのものを取る方法まで確かめます。
description: >
  Math.max(...list) は空配列で -Infinity を返し、null を 0 として扱い、件数が多いと落ちます。
  安全な書き方と、最大値ではなく最大の要素が欲しいときの形を実行して確かめられます。
status: published
difficulty: 2
minutes: 7

versions:
  verified: "Node 22.22.3"
  since: "ES2015"
  deprecated: null
  removed: null

sources:
  - title: "Math.max — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-math.max"
  - title: "Array.prototype.reduce — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-array.prototype.reduce"

terms: [最大値, 畳み込み, 型変換]

links:
  related:
    - javascript/reference/operator/spread
    - javascript/reference/array/reduce
    - javascript/how-to/array/sum

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

## 答え

```js run
const nums = [3, 1, 4];

console.log(Math.max(...nums));
console.log(Math.min(...nums));
```
```output
4
1
```

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

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

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

```js bad
console.log(Math.max(...[]));
console.log(Math.min(...[]));
```
```output
-Infinity
Infinity
```

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

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

```js bad
const prices = [];
const highest = Math.max(...prices);

console.log(`最高額は ${highest} 円`);
```
```output
最高額は -Infinity 円
```

先に確かめてください。

```js run
function max(list) {
  return list.length === 0 ? null : Math.max(...list);
}

console.log(max([3, 1, 4]));
console.log(max([]));
```
```output
4
null
```

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

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

```js bad
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]));
```
```output
3
NaN
10
NaN
```

- `null` は[bad:0 として扱われます]
- `undefined` と `NaN` は[bad:全体を NaN にします]
- 文字列は数値に変換されるので、`'3'` と `'10'` は正しく比べられます

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

```js bad
console.log(Math.max(...[null, -5]));
console.log(Math.min(...[null, 5]));
```
```output
0
0
```

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

```js run
const values = [1, null, 3];

console.log(Math.max(...values.filter((v) => typeof v === 'number')));
```
```output
3
```

→ [なぜ == ではなく === を使うのか](/ja/javascript/why/strict-equality/)

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

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

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

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

```js run
const nums = [3, 1, 4];

console.log(nums.reduce((a, b) => (a > b ? a : b)));
console.log(nums.reduce((a, b) => (a < b ? a : b)));
```
```output
4
1
```

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

```js bad
try {
  [].reduce((a, b) => (a > b ? a : b));
} catch (error) {
  console.log(error.name + ': ' + error.message);
}
```
```output
TypeError: Reduce of empty array with no initial value
```

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

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

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

```js run
const items = [
  { name: 'a', price: 300 },
  { name: 'b', price: 100 },
];

console.log(Math.max(...items.map((item) => item.price)));
```
```output
300
```

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

```js run
const items = [
  { name: 'a', price: 300 },
  { name: 'b', price: 100 },
];

const top = items.reduce((best, item) => (item.price > best.price ? item : best));

console.log(top);
```
```output
{ name: 'a', price: 300 }
```

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

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

```js run
const items = [
  { name: 'a', price: 300 },
  { name: 'b', price: 100 },
];

console.log(items.toSorted((a, b) => b.price - a.price)[0]);
console.log(items[0]);
```
```output
{ name: 'a', price: 300 }
{ name: 'a', price: 300 }
```

`toSorted()` は元の配列を変えないので、`items` はそのままです。
[bad:`sort()` を使うと元が並び替わります。]
→ [配列を数値の大きさで並び替える](/ja/javascript/how-to/array/sort-numbers/)

## 使い分け

| 欲しいもの | 件数が少ない | 件数が多い・不明 |
|---|---|---|
| 最大値 | `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()` で持ち回る
