---
type: reference
language: javascript
slug: array/reduce
title: "Array.prototype.reduce()"
title_tag: "JavaScript reduce() の使い方 — 配列を1つの値にまとめる"
summary: >
  reduce() は配列を1つの値にまとめます。初期値を省いたときの落とし穴、空配列で例外になる条件、
  合計・グループ化の書き方、いつ使わないほうがよいかまでまとめます。
description: >
  配列を1つの値にまとめます。初期値を省くと空配列で例外になる理由、累積値の型を変えるとき、グループ化やオブジェクトの組み立てまで実行して示します。
status: published
difficulty: 3
minutes: 10

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

sources:
  - title: "Array.prototype.reduce — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-array.prototype.reduce"
  - title: "Array.prototype.reduce() — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce"

terms: [累積値, 初期値, コールバック関数, グループ化]

links:
  related:
    - javascript/reference/array/map
    - javascript/learn/array/transform
    - javascript/how-to/array/sum

content_updated_at: 2026-09-07
published_at: 2026-09-07
---

`reduce()` は、配列を[key:1つの値]にまとめます。
[type:累積値]を持ち回りながら、要素を1つずつ畳み込んでいきます。

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

const total = nums.reduce((sum, n) => sum + n, 0);

console.log(total);
```
```output
10
```

第2引数の `0` が[type:初期値]です。**省略できますが、省略しないでください**（理由は後述）。

上のコードは書き換えて実行できます。`sum + n` を `sum * n`、`0` を `1` にしてみてください。

## 引数

| | 中身 |
|---|---|
| 第1引数 | コールバック関数 `(累積値, 要素, 添字, 配列) => 次の累積値` |
| 第2引数 | [type:初期値]（省略可。**省略しないほうがよい**） |
| 戻り値 | 最後の累積値。[key:配列とは限らない] |
| 元の配列 | [em:変わらない] |

## 何が起きているか

累積値がどう渡っていくかを見ます。

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

const total = nums.reduce((sum, n, i) => {
  console.log(`${i}回目: 累積 ${sum} + 要素 ${n} = ${sum + n}`);
  return sum + n;
}, 0);

console.log('結果:', total);
```
```output
0回目: 累積 0 + 要素 1 = 1
1回目: 累積 1 + 要素 2 = 3
2回目: 累積 3 + 要素 3 = 6
結果: 6
```

**返した値が、次の回の第1引数になります。** ここが `map()` との一番の違いです。

`return` を書き忘れると、次の回の累積値が `undefined` になります。

```js bad
const nums = [1, 2, 3];

const total = nums.reduce((sum, n) => {
  sum + n;
}, 0);

console.log(total);
```
```output
undefined
```

## 初期値を省くと危ない

初期値を省くと、**先頭の要素がそのまま最初の累積値**になり、[num:2]番目から回り始めます。

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

console.log(nums.reduce((a, b) => a + b));
console.log(nums.reduce((a, b) => a + b, 0));
```
```output
6
6
```

数の合計なら同じ結果です。**ですが型が違うと壊れます。**

```js bad
const items = [
  { price: 100 },
  { price: 200 },
];

console.log(items.reduce((sum, item) => sum + item.price));
```
```output
[object Object]200
```

最初の累積値が[bad:オブジェクトそのもの]になり、文字列として繋がりました。
初期値 `0` を書けば直ります。

```js run
const items = [
  { price: 100 },
  { price: 200 },
];

console.log(items.reduce((sum, item) => sum + item.price, 0));
```
```output
300
```

### 空配列では例外になる

初期値が無く、要素も無いと、**返すものが決まりません。** 仕様で `TypeError` と定められています。

```js bad
console.log([].reduce((a, b) => a + b));
```
```output
TypeError: Reduce of empty array with no initial value
```

初期値があれば、そのまま返ります。

```js run
console.log([].reduce((a, b) => a + b, 0));
console.log([].reduce((a, b) => a + b, []));
```
```output
0
[]
```

**空配列は普通に起こります**（`filter()` の結果など）。
[key:初期値は必ず書いてください]。

## よく使う形

### 合計・最大

```js run
const scores = [72, 95, 61, 88];

console.log(scores.reduce((sum, n) => sum + n, 0));
console.log(scores.reduce((max, n) => (n > max ? n : max), -Infinity));
console.log(Math.max(...scores));
```
```output
316
95
95
```

[dim:最大値は Math.max(...arr) のほうが短く読めます。ただし要素が数万を超えると RangeError になるので、そのときは reduce にしてください。]

合計まわりの落とし穴（小数・空配列・文字列が混ざる）は
[配列の合計を出す](/ja/javascript/how-to/array/sum/) にまとめてあります。

### 数える

```js run
const votes = ['りんご', 'みかん', 'りんご', 'ぶどう', 'りんご'];

const count = votes.reduce((acc, v) => {
  acc[v] = (acc[v] ?? 0) + 1;
  return acc;
}, {});

console.log(count);
```
```output
{ 'りんご': 3, 'みかん': 1, 'ぶどう': 1 }
```

初期値が `{}` なので、**戻り値は配列ではなくオブジェクト**です。

### グループ化

```js run
const users = [
  { name: 'あかり', team: 'A' },
  { name: 'ゆうと', team: 'B' },
  { name: 'はると', team: 'A' },
];

const byTeam = users.reduce((acc, u) => {
  (acc[u.team] ??= []).push(u.name);
  return acc;
}, {});

console.log(byTeam);
```
```output
{ A: [ 'あかり', 'はると' ], B: [ 'ゆうと' ] }
```

[dim:Object.groupBy() を使うともっと短く書けます（ES2024。Node 21 / Chrome 117 以降）。]

```js run
const users = [
  { name: 'あかり', team: 'A' },
  { name: 'ゆうと', team: 'B' },
  { name: 'はると', team: 'A' },
];

console.log(Object.groupBy(users, u => u.team).A.map(u => u.name));
```
```output
[ 'あかり', 'はると' ]
```

## 使わないほうがよいとき

`reduce()` は何でも書けてしまいます。**書けることと、読みやすいことは別です。**

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

const doubled = nums.reduce((acc, n) => {
  acc.push(n * 2);
  return acc;
}, []);

console.log(doubled);
```
```output
[ 2, 4, 6, 8 ]
```

これは `map()` そのものです。短く、意図もはっきりします。

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

console.log(nums.map(n => n * 2));
```
```output
[ 2, 4, 6, 8 ]
```

| やりたいこと | 使うもの |
|---|---|
| 全部を変換する | [map()](/ja/javascript/reference/array/map/) |
| 条件で絞る | [filter()](/ja/javascript/reference/array/filter/) |
| 最初の1件を探す | [find()](/ja/javascript/reference/array/find/) |
| **1つの値にまとめる** | **`reduce()`** |

**`reduce()` を選ぶのは、出てくる形が[key:元と違う]ときだけ**にしてください。
配列が配列のまま出てくるなら、たいてい別のメソッドが合っています。

### 累積値を毎回作り直さない

短く書きたくてこう書くと、要素の数だけオブジェクトを作り直します。

```js bad
const votes = ['a', 'b', 'a'];

const count = votes.reduce((acc, v) => ({ ...acc, [v]: (acc[v] ?? 0) + 1 }), {});

console.log(count);
```
```output
{ a: 2, b: 1 }
```

結果は合っています。ですが `{ ...acc }` は[bad:毎回まるごと複製]しています。
要素が増えると急に遅くなります。**書き換えて返してください**（上の「数える」の形）。

## 穴のある配列では呼ばれない

[type:疎な配列]の穴では、コールバック関数は呼ばれません。

```js run
const sparse = [1, , 3];
let calls = 0;

const total = sparse.reduce((sum, n) => { calls++; return sum + n; }, 0);

console.log(total);
console.log('呼ばれた回数:', calls);
```
```output
4
呼ばれた回数: 2
```

`map()` と同じ扱いです。`find()` は穴でも呼ばれるので、そこだけ違います。

## 右から畳み込む

`reduceRight()` は末尾から回ります。順序が結果に影響するときだけ使います。

```js run
const parts = ['a', 'b', 'c'];

console.log(parts.reduce((acc, s) => acc + s, ''));
console.log(parts.reduceRight((acc, s) => acc + s, ''));
```
```output
abc
cba
```
