ES6 クイズの答え
ES6 クイズ は、俺自身が「いずれ引っかかりそうだな」と思ったもの。
「そう見えるのは俺だけかも。。」と思って何人かにクイズとして出してみたら、意外と引っかかったので俺だけじゃなさそうと思って書いた。
クイズ1
var a = 1;
if (a => 2) {
console.log('bigger');
} else {
console.log('smaller')
};
// bigger
a => 2
は比較演算ではなく、 arrow function なので常に true
になる。
念のため言うと、本来比較演算の greater than は a >= 2
。
クイズ2
var a = 1, b = 2, c = 3, d = 4;
var f = a => b ? c: d;
// f = ?
1 と全く同じで、 f
は arrow function になる。
(a
と b
の比較なら a >= b
)
わかりやすく書くとこう。
var f = (a) => { b ? c: d; }
つまり、 f
を実行すると、 b
が truthy
なので c
が返る。
f(); // 3
ちなみに AST レベルでは 和田さんが調べてた のでそちらを参照。
本当の問題
この問題、単なる引っ掛けで済めば良いけど、
実際にだれかがこのコードをしれっと入れてしまったときに、気づくのって簡単だろうか。
(たとえ、このエントリを読んで、問題を知っていたとしても。)
特に初心者は、 <=
の反対は =>
だろと思うのは無理も無いと思う。
というかそっちの方が直感的な気もするし。
本当の問題は、「今まで =>
はエラーだった」ということだ。
構文的に間違っていることを処理系が教えてくれたから、俺らは自然とそれを避けてこれた。
でも、 arrow function が有効な環境では、もうこれは Valid なものとして解釈されてしまう。
自分でそれに気づく仕組みを持っておきたいと思うのが、自然なアプローチのように思う。
対策
個人的には、以下のスタイルを強制するのが一番楽だと思う。
(もちろん、テストは書こう。でもその話はしてない。)
arrow function の引数は必ず `()` で囲む
そして、それを強制するための eslint plugin を書いた。
[追記] @teppeis さんの PR で、 Condition が期待される部分のみ検出するルールを追加しました。 no-condition
これを入れれば、以下のようなコードは全て怒られる。
a => {}
a => a
a => {\n}
a.then(foo => {});
a.then(foo => a);
a(foo => { if (true) {}; });
こう直すと通る。
() => {}
(a) => {}
(a) => a
(a) => {\n}
a.then((foo) => {});
a.then((foo) => { if (true) {}; });
このルールを導入していると、クイズのコードはこう書かないと動かなくなり、
もし比較演算を意図していたなら、おかしいことに気づけると思う。
if ((a) => 2) {
// snip
}
var f = (a) => b ? c: d;
中括弧や return
まで強制すればもっと良いかもしれないけど、それは arrow function の旨味まで消えている気がするので、
スタイルで強制するのはこのくらいがちょうどいいと思う。今のところ違和感は感じてない。
なお、「今まで動かなかったコードが動くようになる」ということがもたらす問題に、これからもっと直面するだろうなと思う。