bind operator proposalとは?
ECMAScriptへの新しい文法の提案の1つ。
-
obj::func()
と書けばfunc.call(obj)
になる -
::obj.method
と書けばobj.method.bind(obj)
になる
という新しい文法を提案している。
babelですでに実装されており、熱烈なサポーターもいるが、
TC39 stageは未だに0。 (TC39のstageについてはazuさんのECMAScriptとは何か?に詳しい)
もう一方の期待の新星 async/await が着々とstageを上げているなか、何故bind operator proposalは一向に進まないのか。
本記事は主に、その理由として挙げられている下記のgithub issuesの流れをまとめたものである。
- What's keeping this from Stage 1 - issue#24 proposal-bind-operator
- Why is this still stage 0? - issue#35 proposal-bind-operator
bind operator proposalが進まない理由
紐解いていくと、2つの課題があった。
- TC39のメンバーで推進役がいない
- 2つの別な機能が別々な問題を抱えている
推進役 = champion の不在
各提案にはchampionと呼ばれる、TC39のmemberで、この提案を推し進める代表的存在が必要なのだという。
この提案にもchampionはいたが、彼はすでにTC39のmemberとしては働いていなかった。
今年7月に、別なmemberが「私がchampionになります」という発言をして盛り上がりを見せたが、それっきり出番がないような状況だ。
2つの別な機能を1つで提案している
実はこの提案は、2つの別な機能の提案になっている。
-
obj::func()
と書けばfunc.call(obj)
になる機能 -
::obj.method
と書けばobj.method.bind(obj)
になる機能
issue内では、1をinfix notationと表現し、2をprefix notationと表現していたが、それぞれが別な課題を抱えていた。
infix notationの動的thisの変更は混乱を招く
infix notationは、thisを、敢えて、動的に変える、という操作だ。
これは混乱のもとになるのではないか。
ES2015では、古来からJSに存在した「thisが変わるってどういうこと?」問題に取り組み、thisを束縛する関数定義の文法を作ったのだが、
このinfix notationは、その方針に逆行しまいか、ということである。
prefix notationは見た目がよくない
prefix notationが解決するのは、
arr.forEach(...args => console.log(...args))
を、
arr.forEach(::console.log)
にすることだ。(実際にはconsole.logはthisがなくても動作するようになってきているようだが)
Reactなどで下位のコンポーネントにthisを束縛した状態でメソッドを渡したい場合にも有効だ。
しかし、他のプログラミング言語で、::
から始まる構文がない(あったらコメントよろしく)ため、
見た目がよくなく感じるのだろう。
別で提案するのがよいのか
infix notationとprefix notationは、待ちわびている層が違う印象がある。
RxJS勢はinfix notationを待ちわびている。
underscoreやlodashのようなutility系も、この文法が取り入れられたら、thisをベースにするものに置き換えられていくだろう。
一方prefix notationは、「あったら便利だよね」「v8はbindに比べて最適化できる余地がありそう」といった程度で、そこまで急ぐ理由も見えない、という印象がある。
ただ多くのイベント駆動型ライブラリ、もちろんReactでも、小さな幸せを手に入れることができる。
個人的にはredux sagaのSVO記法(主語、動詞、目的語の順に引数に入れて関数呼び出しを宣言的に書くもの)などが今後増えるときに、より便利になるのではないかと思う。
このように、解決したい課題も違うし、抱えている問題も違うので、分けてしまえばいいのではという意見があった。
しかし、分けたら分けたで、2人のchampionが必要になり、自体は混迷を極めている...。
ファンとして
infix operatorは劇薬的だ。魅力的だが、乱暴な使い方が怖い。
1人で楽しむ分には最高だが、チームだと「このthisはどこに使われる想定なん?」となる。
だから、filter
やmap
など、汎用の処理群でのみ使われる世界になるように、
利用側が行儀よくしている必要がありそうだ。
prefix operatorは、最適化のカギになってくれという期待がある。
例えばReactで、
<SomeComponent onClick={::this.sendSomething} />
これがしたいが、これは(軽微だが)パフォーマンス問題がある。
コンストラクタで一度だけbindするのが筋だということだ。
でも、**「bind関数じゃなくて文法なので、最適化でパフォーマンス問題を解決してくれる」**的な
未来を期待している。
来年からは、ファンはやきもきしているだけでなく、もっと態度で示していけるよう、
コミュニティを盛り上げられればと思う。