LoginSignup
37
34

More than 5 years have passed since last update.

arrow function の引数は括弧で囲っておいた方が良さそうな件

Last updated at Posted at 2015-04-28

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 になる。
(ab の比較なら a >= b)

わかりやすく書くとこう。

var f = (a) => { b ? c: d; }

つまり、 f を実行すると、 btruthy なので 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 の旨味まで消えている気がするので、
スタイルで強制するのはこのくらいがちょうどいいと思う。今のところ違和感は感じてない。

なお、「今まで動かなかったコードが動くようになる」ということがもたらす問題に、これからもっと直面するだろうなと思う。

37
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
34