ArrowFunction 的即時関数
ある意味、ソーシャルボタンのJavaScriptでfunctionの前に「!」がついている理由の続き。
今回は ECMAScript 6th から入る ArrowFunction で即時関数を考える巻。
前回は普通の関数式での即時関数を解説してみた。
- functionには2種類ある
- いきなり function から書くと式とは認識されないから一工夫が必要
という話だった。
さて、もし、function には1種類しかなく、式としての関数式のみだったら、きっと ExpressionStatementの先頭にfunction
が来てはならないという宣言が設けられることは無かっただろう。
それを踏まえて、ArrowFunctionを見てみると、これは1種類の式のみの定義だ。
では、
() => { // .... }();
と書けるはず! と思うだろう。
しかし、しかしながら、こう書くと構文エラーになる。
(() => { // ... })();
と書かなければいけない。わざわざ()で囲まなくてはならないのだ。
注意
今回の話は、あくまで ECMAScript 6th Draft rev14 での話であって、以降のバージョンから修正される可能性がある、と注意書きしておきたい。
( ArrowFunction )() でないといけない理由
前の話で、関数/メソッド実行をするには CallExpression である必要があると書いた。
CallExpression の定義は以下のようになっている。
CallExpression : MemberExpression Arguments CallExpression Arguments CallExpression [ Expression ] CallExpression . IdentifierName
定義するものの中に、その定義が入っていて再帰呼び出しの様になっていて少々難解だが、結局のところ実行を示す ()
Arguments の前は MemberExpression である必要があるというものになっている。
そして、MemberExpression の定義は以下のようになっている。
MemberExpression : PrimaryExpression FunctionExpression MemberExpression [ Expression ] MemberExpression . IdentifierName new MemberExpression Arguments
MemberExpression は FunctionExpression(関数式)を含む、という定義になっている。
これで、function(){ ... }()
というFunctionExpression Arguments
な書き方が許可されていることが分かる。
では、ArrowFunction はどうだろうか。
ドラフト仕様(http://people.mozilla.org/~jorendorff/es6-draft.html) を見てみると、ArrowFunction が登場するのは AssignmentExpression というところであるが、MemberExpression から連なる定義を追っていっても AssignmentExpression に繋がる導線は一つしか見つからない。
PrimaryExpression中にある、( Expression )
である。
PrimaryExpression : this Identifier Literal ArrayLiteral ObjectLiteral ( Expression )
よって、ArrowFunction で即時関数を作りたかったら () で囲むしかないことが分かる。
仕様バグなんじゃね?
実は Mozilla の Bugzilla に既に挙げられていて、() で囲まなくてはならないのは仕様バグであって Mozilla のバグじゃないと RESOLVE INVALID で閉じられている。
ということで、次回のど Draft 仕様で修正されて、MemberExpressionあたりの中に ArrowFunction が登場するのではないかと、密かに思っていたり。
まとめ
以上、毒にもクスリにもならない話。
または、仕様を読むと謎が解けるよ!って話。
余談
即時関数は IIFE なんて海外では書かれていることがあるが、IIAFE などというのも登場してたり。
Axel Rauschmayer さんが、ES6 にはブロックスコープがあるんだから不要だろ的なことを返信してるけどね。