【JS】JavaScriptのバッククォートとカリー化の相性良すぎ問題
こんにちは!今日はJavaScriptのデザインパターンの一つ、バッククォート+カリー化について紹介します。
関数がめっちゃ綺麗になるぞ…!
結論
こういう書き方ができます
const greet = type => person => name =>
`${type[0]}! ${person[0]} name is ${name[0]}.`
~greet`Hello``My``Mike`
// Hello! My name is Mike.
バッククォートの関数呼び出し
すごい簡単に言うと、関数を**こんなかんじ()じゃなくてこんなかんじ“**に呼び出せるってことです↓
const hello1 = name => `I'm ${name} .`
const hello2 = name => `I'm ${name[0]} .`
hello1('Mike') // I'm Mike.
hello2`Mike` // I'm Mike.
こちらの記事で色々書いてるわ。
カリー化
カリー化はあれだ、詳しくはwikipedia見てもらうとして
要はn個の引数をとる関数を1個の引数をとるn個の関数にバラす感じ。こんな風に。
const sum1 = (n, m) => n + m
const sum2 = n => m => n + m
sum1(10, 32) // 42
sum2(10)(32) // 42
バッククォートとカリー化を合体させてみよう
3つの引数をとる関数【greet】を想定します。それぞれ、【挨拶】【人称】【名前】をとって、【こんにちは】!【僕】の名前は【マイク】です! みたいな文章を作ります。
普通に書く
普通に書くとこう。
const greet = (type, person, name) => `${type}! ${person} name is ${name}.`
~greet('Hello', 'My', 'Mike')
// Hello! My name is Mike.
まあ全然読める。綺麗。ちなみにチルダ(~)はおまじないみたいなもんです。戻り値使わない関数には付けておこう。!や;でもいいよ。
バッククォートにしてみる…?
バッククォートにしてみたいけどバッククォートの関数呼び出しは引数1つしかとれんので一旦保留。
カリー化してみる
カリー化なら簡単。こう。
const greet = type => person => name => `${type}! ${person} name is ${name}.`
~greet('Hello')('My')('Mike')
// Hello! My name is Mike.
うーん綺麗になったかは微妙なところ?関数側は綺麗になったけど、呼び出し側は冗長に見えます。
バッククォート+カリー化
本題。どうぞ
const greet = type => person => name =>
`${type[0]}! ${person[0]} name is ${name[0]}.`
~greet`Hello``My``Mike`
// Hello! My name is Mike.
えっやばい…呼び出し側がめっちゃ綺麗。関数側汚くなってるけどな
まだ驚くことなかれ、これちょっと適当にインデントして、他の例も書いてみると…
const greet = type => person => name =>
`${type[0]}! ${person[0]} name is ${name[0]}.`
~greet`Hello``My``Mike`
// Hello! My name is Mike.
~greet`Hi``Our``Team Mike`
// Hi! Our name is Team Mike.
もはやJSではない。いやこれが真のJSか。別言語。もう別言語。 さすがにここまでインデントするのはやりすぎだけど、新世界が見えた。
実用例
【.このclass】を【クリック】したら【このメッセージ出す】みたいな処理考える。
const greet = name => event => greet =>
document
.querySelectorAll(name[0])
.forEach(e => e.addEventListener(event[0], _ => alert(greet[0])))
~greet`.greet-button``click``こんにちは!クリックしてくれてありがとう!`
~greet`.greet-area``onmouseover``こんにちは!ここは挨拶エリア`
~greet`.confirm``click``本当によろしいですか?`
呼び出し側がシンプルすぎる。関数側はカオス。
ライブラリとかに使えそう?
さいごに
バッククォート+カリー化、特に呼び出し側はめっちゃ綺麗になる。一方で関数はカオスになる。
ライブラリとか共通の関数みたいな、処理がブラックボックス化できるケースでやるとよさそう。
あと例のごとくIEは全く駄目だ
以上!