関数型プログラミング
Reactで関数型プログラミングの知識も必要そうなので、こちらもざっと学習した内容をメモ。
高階関数
引数に関数をとったり、戻り値として関数を返したりする関数のこと。 下記だと(4 + 1) × 2 = 10 が実行される。 英語では Higher Order Function というが、ReactのHOC(Higher Order Component)と原理は同じなので、理解しておくと楽らしい。
const hof = (ex, fn) => { return n => fn(n + ex); }; const plusOneDouble = hof(1, n => n * 2); console.log(plusOneDouble(4)); // 10
クロージャ(関数閉包)
以下はクラスで実行ごとに1加算されるカウンター。 クラスを呼び出すごとに、その値を加算していく。 これを関数で普通に作ろうとするとグローバル変数を定義する等の方法を用いざるを得ず、なかなか難しい。
class Counter { constructor(initialCount) { this.c = initialCount; } increment() { return this.c++; } } const counter = new Counter(1); console.log(counter.increment(), counter.increment(), counter.increment()); // 1 2 3
そこで以下のようにクロージャを使う。 こうすることによって変数 c の値が実行ごとにクリアされることなく加算される
const counterMaker = (initialCount) => { let c = initialCount; const increment = () => c++; return increment; }; const count = counterMaker(1); console.log(count(),count(),count()); //123
ジェネレータ
その他にもJavaScriptでは値を保持しつつ繰り返し処理や逐次処理を行うための手段としてジェネレータ関数がある。
戻り値のオブジェクトから next()という関数かを実行できる。 それによ って yield で返された値がその戻り値オブジェクトの value プロパティに格納される。 そしてそれ以 上ジェネレータの中で yield 文が実行されることがなくなると、value プロパティは undefined になり、 done プロパティが true になる。
function* rangeGenerator(end, start = 0) { letn=0; for(leti=start;i<end;i++){ n+=1; yield i; } } const gen = rangeGenerator(3); console.log(gen.next()); // { value: 0, done: false } console.log(gen.next()); // { value: 1, done: false } console.log(gen.next()); // { value: 2, done: false } console.log(gen.next()); // { value: undefined, done: true }
カリー化
端的にいうと複数の引数をとる関数を、ひとつだけ引数をとる関数に分割してネストさせること。 下記のように高階関数を使い、ひとつずつの値を返す関数がネストした高階関数にすることかをカリー化と言う。 2つ目と3つ目の書き方になるが、よりシンプルな3つ目の書き方が望ましい。
constmulti=(n,m)=>n*m; console.log(multi(2, 4)); //8 const curriedMulti = n => { returnm=>n*m; } console.log(curriedMulti(2)(4)); // 8 カリー化 const simpleCurriedMulti = n => m => n * m; console.log(simpleCurriedMulti(2)(4)); //8 カリー化のよりシンプルな書き方
カリー化関数の部分適用
以下の場合、triple は カリー化された高階関数multi のひとつめの引数に3を渡した関数。 こうするとどんな数を渡しても、常に3倍される関数が作れるので便利。
このようにカリー化された関数の一部の引数を固定して新しい関数を作ることを関数の 部分適用と言う。 無駄をなくし、再利用性を高め可読性を上げる。
constmulti=n=>m=>n*m; console.log(multi(3)(5)); // 15 const triple = multi(3); console.log(triple(5)); // 15 カリー化の部分適用