概要
隣り合う 2 つの配列要素に対して(左から右へ)同時に関数を適用し、単一の値にします。
構文
var result = array.reduce(callback[, initialValue]);
引数
callback- 4 つの引数を取って、配列内の各値に対し実行するコールバック関数
previousValue- 現在処理されている配列要素の 1 つ前の要素。もしくは、
initialValue。initialValueについては、後で述べます。 currentValue- 現在処理されている配列要素
index- 現在処理されている配列要素のインデックス
arrayreduceに呼ばれた配列
initialValuecallbackの最初の呼び出しのときに、最初の実引数として用いるためのオブジェクト。
詳細
reduce は、配列に存在するおのおのの要素に対して、callback 関数を一度だけ実行します。配列における穴は対象からはずされ、また callback 関数は 「初期値(あるいは、直前の callback 呼び出し)」、「現在の要素の値」、「現在のインデックス」、「繰り返しが行われる配列」 の 4 つの引数を受け取ります。
reduce の callback の呼び出しは、以下のように見えるでしょう。:
arrayObj.reduce(function(previousValue, currentValue, index, array){
// ...
})
関数が呼び出される初回は、 previousValue と currentValue は 2 つの値のうちの 1 つを取り得ます。reduce 呼び出し時に、initialValue が与えられた場合、previousValue は initialValue と等しくなり、currentValue は、配列の最初の値と等しくなります。 initialValue が与えられなかった場合、previousValue は配列の最初の値と等しくなり、currentValue は、2 番目の値と等しくなります。
次のコードのように reduce を使用した場合について見てみましょう。
[0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){
return previousValue + currentValue;
});
コールバック関数は 4 回呼び出され、各回の引数の内容は以下のようになっています。
previousValue |
currentValue |
index |
array |
戻り値 | |
|---|---|---|---|---|---|
| 初回の呼出し | 0 |
1 |
1 |
[0,1,2,3,4] |
1 |
| 2 回目の呼出し | 1 |
2 |
2 |
[0,1,2,3,4] |
3 |
| 3 回目の呼出し | 3 |
3 |
3 |
[0,1,2,3,4] |
6 |
| 4 回目の呼出し | 6 |
4 |
4 |
[0,1,2,3,4] |
10 |
reduce の戻り値は、コールバック関数の最後の戻り値である(10)となるでしょう。
reduce の 第二引数に初期値を設定した場合は、コールバック各回の内部的な動作はこのようになります。
[0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){
return previousValue + currentValue;
}, 10);
previousValue |
currentValue |
index |
array |
戻り値 | |
|---|---|---|---|---|---|
| 初回の呼出し | 10 |
0 |
0 |
[0,1,2,3,4] |
10 |
| 2 回目の呼出し | 10 |
1 |
1 |
[0,1,2,3,4] |
11 |
| 3 回目の呼出し | 11 |
2 |
2 |
[0,1,2,3,4] |
13 |
| 4 回目の呼出し | 13 |
3 |
3 |
[0,1,2,3,4] |
16 |
| 5 回目の呼出し | 16 |
4 |
4 |
[0,1,2,3,4] |
20 |
reduce の戻り値はもちろん 20 となります。
互換性
reduce は、ECMA-262 第 5 版に追加された仕様であり、他の標準の実装には存在しない場合があります。以下のコードをあなたのスクリプトの最初に挿入することにより、実装の如何に関わらずこれを動作させる事ができます。
if (!Array.prototype.reduce) {
Array.prototype.reduce = function reduce(accumulator){
if (this===null || this===undefined) throw new TypeError("Object is null or undefined");
var i = 0, l = this.length >> 0, curr;
if(typeof accumulator !== "function") // ES5 : "If IsCallable(callbackfn) is false, throw a TypeError exception."
throw new TypeError("First argument is not callable");
if(arguments.length < 2) {
if (l === 0) throw new TypeError("Array length is 0 and no second argument");
curr = this[0];
i = 1; // start accumulating at the second element
}
else
curr = arguments[1];
while (i < l) {
if(i in this) curr = accumulator.call(undefined, curr, this[i], i, this);
++i;
}
return curr;
};
}
例
例: 配列内の値を全て足す
var total = [0, 1, 2, 3].reduce(function(a, b) {
return a + b;
});
// total == 6
例: 二次元配列を 一次元配列にする
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
return a.concat(b);
});
// flattened is [0, 1, 2, 3, 4, 5]
ブラウザ実装状況
Kangax's compat tables に基づく。
| 機能 | Firefox (Gecko) | Chrome | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|
| 基本サポート | 3.0 (1.9) | (有) | 9 | 10.5 | 4.0 |
| 機能 | Firefox Mobile (Gecko) | Android | IE Mobile | Opera Mobile | Safari Mobile |
|---|---|---|---|---|---|
| 基本サポート | ? | ? | ? | ? | ? |