Array.prototype.reduce TIPS
概要
先週の土曜日に開催されたGunma.web #35にて発表した内容に一部追記した記事です。
* 記事内のcodepen blockについて
コードブロックは実行済みの状態で表示されているので、動作を確認したい場合は、各コードブロックエディタの右下にある を押して再度実行してください。
Array.reduceとは
reduceメソッドは、配列の各要素に対して順番にコールバック関数を実行します。
コールバック関数の一つ目の引数は、アキュームレーターと呼ばれ、コールバック関数が処理された際の戻り値が次のコールバックの引数として渡されます。
1 2 3 4 |
//書式 Array.reduce(コールバク関数(アキュームレーター, 値, インデックス, 配列){ return 戻り値 }, 初期値) |
このメソッドは非常に使い勝手がよく、応用範囲が広いのでその一部を紹介したいと思います。
総和を求める
reduceメソッドのサンプルとしてよく紹介されるコードです。
配列に収められた値の総和をreduceを使うことで簡潔に求めることができます。
[codepen_embed height=”500″ theme_id=”dark” slug_hash=”WBPozv” default_tab=”js,result” user=”shimizu”]See the Pen reduce sample – sum by shimizu masayuki (@shimizu) on CodePen.[/codepen_embed]
動作解説
1 2 3 4 5 6 7 8 9 10 |
配列:[1,2,3,4,5] 初期値: 0 callback1 -> 0 + 1 -> 1 //初期値に配列[0]の値が加算される callback2 -> 1 + 2 -> 3 //戻り値に配列[1]の値が加算される callback3 -> 3 + 3 -> 6 // ... callback4 -> 6 + 4 -> 10 // ... callback5 -> 10 + 5 -> 15 // 全ての値が加算される //-> 15 |
なにが便利なのか?
プログラムでは、「前の処理の結果を受けて次の処理を行う」という順番が重要となる連結処理が頻出します。reduceメソッドを使うことで、連結処理を簡潔に記述することができます。
ここからは、reduceメソッドを使って逐次処理を行うサンプルを紹介します。
ファンクション・チェイン
複数の関数をreduceを使って連続的に処理します。
その際、直前に実行された関数の戻り値を引数として受け取ります。
関数を入れ子にしたり、スコープ外に余計なテンポラリ変数を設定しなくてもよいので、すっきりと記述することができます。
[codepen_embed height=”500″ theme_id=”dark” slug_hash=”zQeoJP” default_tab=”js,result” user=”shimizu”]See the Pen reduce sample – chain functions by shimizu masayuki (@shimizu) on CodePen.[/codepen_embed]
プロミス・チェイン
非同期処理を同期的に逐次処理したい場合にもreduceを活用することができます。
通常のthenメソッドを用いたチェインやPromise.allでは実現するのが難しい連続処理も配列を使って記述することができます。
[codepen_embed height=”500″ theme_id=”dark” slug_hash=”JqxWVE” default_tab=”js,result” user=”shimizu”]See the Pen reduce sample – chain promise by shimizu masayuki (@shimizu) on CodePen.[/codepen_embed]
Redux/Reducer
Reduxに含まれる機能の一つであるReducerは、現在のステートとステートを変更させる指示(アクション)を受け取り、新しいステートを生成します。
reducerを副作用のない純粋関数で記述することで、照透過性を保ったままステートのハンドリングを行うことができます。
ここでは、Pure Javascriptのreduceを使って簡易的なReducerを実装してみます。
ベースとなるファンクション・チェイン
先ほど紹介したファンクション・チェインをベースとしてreducer風に書き換えて行きます。
[codepen_embed height=”500″ theme_id=”dark” slug_hash=”zQeoJP” default_tab=”js,result” user=”shimizu”]See the Pen reduce sample – chain functions by shimizu masayuki (@shimizu) on CodePen.[/codepen_embed]
関数を直接渡すのではなく、アクションを渡してreducerの中で処理をするように変更
[codepen_embed height=”500″ theme_id=”dark” slug_hash=”jodBoj” default_tab=”js,result” user=”shimizu”]See the Pen reduce sample – chain functions2 by shimizu masayuki (@shimizu) on CodePen.[/codepen_embed]
さらにRedux/Reducer風に
[codepen_embed height=”500″ theme_id=”dark” slug_hash=”MdLpNY” default_tab=”js,result” user=”shimizu”]See the Pen reduce sample – chain functions3(reducer) by shimizu masayuki (@shimizu) on CodePen.[/codepen_embed]
まとめ
reduceを使うと、関数と関数の間での値の受け渡しを副作用のない形で記述することができます。複雑な逐次処理も、意外と簡潔に記述できたりするのでぜひ使ってみてください。