Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
This feature is well established and works across many devices and browser versions. It’s been available across browsers since 2015年7月.
reduce() は Array インターフェイスのメソッドで、配列のそれぞれの要素に対して、ユーザーが提供した「縮小」コールバック関数を呼び出します。その際、直前の要素の計算結果の返値を渡します。配列のすべての要素に対して「縮小」コールバック関数を実行した最終結果は、単一の値となります。
コールバックの初回実行時には「直前の計算の返値」は存在しません。初期値が与えらえた場合は、代わりに使用されることがあります。そうでない場合は、配列の要素 0 が初期値として使用され、次の要素(0 の位置ではなく 1 の位置)から反復処理が開始されます。
配列の各要素に対して実行される関数です。その返値は、次に callbackFn を呼び出す際の accumulator 引数の値になります。最後の呼び出しでは、返値は reduce() の返値となります。この関数は以下の引数で呼び出されます。
accumulator前回の callbackFn の呼び出し結果の値です。初回の呼び出しでは initialValue が指定されていた場合はその値、そうでない場合は array[0] の値です。
currentValue現在の要素の値です。初回の呼び出しでは initialValue が指定された場合は array[0] の値であり、そうでない場合は array[1] の値です。
currentIndexcurrentValue の位置です。初回の呼び出しでは、 initialValue が指定された場合は 0、そうでない場合は 1 です。
arrayreduce() が呼び出された配列です。
initialValue 省略可コールバックが最初に呼び出された時に accumulator が初期化される値です。 initialValue が指定された場合、callbackFn は配列の最初の値を currentValue として実行を開始します。 もし initialValue が指定されなかった場合、accumulator は配列の最初の値に初期化され、callbackFn は配列の 2 つ目の値を currentValue として実行を開始します。この場合、配列が空であれば(accumulatorとして返す最初の値がなければ)エラーが発生します。
配列全体にわたって「縮小」コールバック関数を実行した結果の値です。
配列に要素がなく、かつ initialValue が提供されなかった場合に発生します。
reduce() メソッドは反復処理メソッドです。「縮小」コールバック関数を配列に含まれる各要素に対して昇順に一度ずつ呼び出し、その結果を単一の値に積算します。毎回、 callbackFn の返値は次回の callbackFn の呼び出しで accumulator として渡されます。最終的な accumulator の値(配列の最終反復処理において callbackFn から返される値)が reduce() の返値となります。これらのメソッドが一般的にどのように動作するのかについての詳細は、反復処理メソッドの節をご覧下さい。
callbackFn は値が割り当てられている配列インデックスに対してのみ呼び出されます。疎配列の空のスロットに対しては呼び出されません。
他の反復処理メソッドとは異なり、 reduce() は thisArg 引数を受け入れません。 callbackFn は常に undefined を this として呼び出され、 callbackFn が厳格モードでない場合は globalThis に置き換えられます。
reduce() は関数型プログラミングの中心的な概念です。ここでは、どの値も変異させることができないので、配列のすべての値を積算するには、反復処理のたびに新しい積算値を返さなければなりません。この約束事は JavaScript の reduce() にも当てはまります。スプレッド構文や他の可能な限りコピーする方法を使用して、既存のものを変更せずに、アキュームレーターとして新しい配列やオブジェクトを作成すべきなのです。もし、アキュームレーターをコピーする代わりに変化させることにした場合、コールバックで変更したオブジェクトを返すことを忘れないでください、さもなければ、次の反復処理で undefined を受け取ることになります。ただし、アキュムレーターをコピーすると、メモリー使用量が増加し、パフォーマンスが低下する可能性があることに注意してください。詳細については、 reduce() を使用すべきでない場合用しない場合 を参照してください。このような場合、パフォーマンスの低下やコードの可読性の低下を避けるために、代わりに for ループを使用することをお勧めします。
reduce() メソッドは汎用的です。これは this 値に length プロパティと整数キーのプロパティがあることだけを期待します。
配列が(位置に関わらず) 1 つの要素しか持たず、 initialValue が指定されなかった場合、または initialValue が指定されていても配列が空だった場合、 callbackFn は実行されずに要素が返却されます。
initialValue が提供され、配列が空でない場合、 reduce メソッドは常に 0 の位置からコールバック関数を呼び出し始めます。
initialValue が提供されなかった場合、 reduce メソッドは、次の例に示すように、長さが 1 より大きい配列、長さが 1 の配列、長さが 0 の配列に対して異なる動作をします。
下記のコードは、初期値がない場合に配列に reduce() を呼び出したときに何が起こるかを示します。
コールバック関数は 4 回呼び出され、各回の引数の内容は以下のようになります。
| 最初の呼び出し | 15 | 16 | 1 | 31 |
| 2 番目の呼び出し | 31 | 17 | 2 | 48 |
| 3 番目の呼び出し | 48 | 18 | 3 | 66 |
| 4 番目の呼び出し | 66 | 19 | 4 | 85 |
array の要素は処理中に変化しません。常に [15, 16, 17, 18, 19] です。 reduce() の返値は、コールバック呼び出しの最後の返値である (85) となるでしょう。
ここでは、同じアルゴリズムで同じ配列を減らしますが、 reduce() の 2 番目の引数として 10 という initialValue を渡します。
コールバックは 5 回呼び出され、それぞれの呼び出しにおける引数と返値は次のようになります。
| 最初の呼び出し | 10 | 15 | 0 | 25 |
| 2 番目の呼び出し | 25 | 16 | 1 | 41 |
| 3 番目の呼び出し | 41 | 17 | 2 | 58 |
| 4 番目の呼び出し | 58 | 18 | 3 | 76 |
| 5 番目の呼び出し | 76 | 19 | 4 | 95 |
この場合の reduce() の返値は 95 となります。
オブジェクトの配列に含まれた値の合計値を出すには、すべての項目を関数内で取得できるようにするために initialValue を指定する必要があります。
pipe 関数は一連の関数を受け取り、新しい関数を返します。新しい関数が引数で呼び出されると、一連の関数が順番に呼び出され、それぞれが前回関数の返値を受け取ります。
プロミスシーケンスは、非同期で行われることを除けば、基本的に前回の節で示された関数のパイプ接続です。
asyncPipe は async/await を使用して実装することもでき、 pipe との類似性をよりよく示しています。
reduce() は疎配列の欠落している要素をスキップしますが、値が undefined の場合はスキップしません。
reduce() メソッドは this の length プロパティを読み込み、次にキーが length より小さい非負の整数である各プロパティにアクセスします。
reduce() のような多目的の高次関数は強力ですが、特に経験の浅い JavaScript の開発者にとっては理解しにくい場合があります。他の配列メソッドを使用した方がコードが明快になる場合、開発者は reduce() を使用する他の利点と読み取り可能性のトレードオフを比較検討する必要があります。
reduce() は常に for...of ループと同等ですが、上位スコープの変数を変更する代わりに、各反復処理で新しい値を返すことに注意してください。
前述のように、人々が reduce() を使用したいと思う理由は、データを不変とする関数型プログラミングの手法を模倣するためです。したがって、アキュムレーターの不変性を支持する開発者は、次のように反復処理ごとにアキュムレーター全体をコピーする傾向があります。
このコードは非効率的です。というのも、各イテレーターは allNames オブジェクト全体をコピーする必要があり、これは固有の名前がいくつあるかによってサイズが大きくなってしまうからです。このコードは最悪の場合、 N が names の長さだとすると O(N^2) のパフォーマンスになります。
各反復処理で allNames オブジェクトを変更したほうがよりよいでしょう。しかし、 allNames がいずれにせよ変更されるのであれば、 reduce() を for ループに変換した方がより明確です。
したがって、アキュムレーターが配列やオブジェクトで、反復処理ごとに配列やオブジェクトをコピーしている場合、誤ってコードに 2 次的な複雑さを導入してしまい、大きなデータですぐにパフォーマンスが低下してしまう可能性があります。これは実際のコードでも現れています。例えば、 Making Tanstack Table 1000x faster with a 1 line change を参照してください。
reduce() の受け入れられる用途のいくつかは上で指定されたものです(特に、配列の合計、プロミスの順序付け、関数のパイプ処理)。他にも reduce() よりも優れた代替手段が存在する場合があります。
配列の平坦化。代わりに flat() を使用してください。
プロパティによるオブジェクトのグループ化。代わりに Object.groupBy() を使用してください。
オブジェクトの配列に格納されている配列の連結。代わりに flatMap() を使用してください。
配列内の重複項目の除去。代わりに Set と Array.from() を使用してください。
配列の要素の削除や追加。代わりに flatMap() を使用してください。
配列から要素を取り除くだけなら filter() も使用できます。
要素の検索、または要素が条件を満たすかどうかのテスト。代わりに find() と findIndex() または some() と every() を使用してください。これらのメソッドには、配列全体を反復処理することなく、結果が確定したらすぐに返すという好ましいこともあります。
reduce() が最良の選択である場合は、ドキュメント化と変数名の意味づけをすることで、可読性の欠点を軽減する手助けになります。
| ECMAScript® 2027 Language Specification # sec-array.prototype.reduce |
Enable JavaScript to view this browser compatibility table.
This page was last modified on 2025年8月9日 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.