概要
Array.prototype.reduce()
メソッドは、配列の要素を一つずつ取り出しながら畳み込み処理し、一つの値を返すメソッド。
要素の合計や最大値の取得といった基本的な処理もこのメソッドで実装する。
書式
reduce()
メソッドは引数にコールバック関数をとる。
[配列].reduce(callback[, initial_value]);
コールバック関数がとるべき引数は決まっている。
callback(accumulator, current_value[, index[, array]])
処理の概要
initial_value
が指定されない場合、以下のように処理される。
- 配列の最初の要素の値が
accumulator
にセットされる- 要素数が1の場合には、そのまま終了
- 要素数が2の場合には、2番目の要素の値が
current_value
にセットされる
- 最後の要素に達するまで、定義された関数の処理を行い、
curren_value
を次の要素の値とする
initial_value
が指定された場合は、accumulator
の初期値としてinitial_value
が使われ、最初のcurrent_value
には1つ目の要素の値がセットされる。通常、initial_value
を指定しておく方が安全。
畳み込みの途中結果はaccumulator
に保存されていくが、戻り値は処理内容に応じてユーザーが定義する。
基本的な例
要素の合計
以下の例では、配列の要素の合計値を求めている。
関数定義では、各要素をスキャンするごとにその値をaccumulator
に足しこんでいる。その結果、最後の要素に達した時にaccumulator
の値は要素の合計値となっている。
1 2 3 4 5 6 7 8 |
var sum = function(accumulator, current_value) { return accumulator + current_value; } var data = [2, 1, 4, 3]; console.log(data.reduce(sum)); // 10 |
要素の最大値
以下の例では、配列の要素の最大値を求めている。
accumulatorの値は要素をスキャンするごとにより大きい値へと書き換えられ、実行終了時には要素のうち最大の値となっている。
1 2 3 4 5 6 7 8 |
var max = function(accumulator, current_value) { return current_value >= accumulator ? current_value : accumulator; } var data = [2, 1, 4, 3]; console.log(data.reduce(max)); // 4 |
処理過程の確認
reduce()のイテレーション各回でaccumulatorやcurrent_valueがどのように推移するか確認してみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
display_process = function(accumulator, current_value) { console.log(accumulator, current_value); } console.log([1, 2, 3].reduce(display_process)); // 1 2 // undefined 3 // undefined console.log([1].reduce(display_process)) // 1 console.log([1, 2, 3].reduce(display_process, 0)); // 0 1 // undefined 2 // undefined 3 // undefined console.log([1].reduce(display_process, 0)) // 0 1 // undefined |
コールバック関数の戻り値がないため、2回目以降のイテレーションでaccumulator
の内容がundefined
になっている。逆に言えば、reduceのイテレーションごとにコールバックの戻り値をaccumulater
に渡している。
イテレーションの最後でcurrent_value
の値がundefined
、null
、empty
などのいずれでもない理由は不明。
initial_valueの指定の有無によって、accumulator、current_valueの各回の値やイテレーション回数が異なっている点に注意。