Firefox 22(Nightly) で ArrowFunction が実装されたが、扱いが難しい
ということで、早速試しているわけです。
基本
var f1 = () => "OK"; // 引数なしの場合は、"()"が必須 var f2 = arg => arg + 1; // 引数一つなら、"()"は省略可 var f3 = (arg1, arg2) => arg1 + arg2; // 複数の引数の場合は"()"必須 var f4 = arg => { // ステートメントを入れる場合は "{}" でブロックを生成する if (arg) return "OK"; else return "NG"; }; // オブジェクトを返す場合は、ブロックと間違われないように // ({...}) と () 等を使用する var f5 = () => ({ a: "A", b: "B" }); var odds = [1, 2, 3, 4, 5].filter(n => n % 2); // [1, 3, 5]
また、単純なfunction
の省略形ではない。
() => "OK";
は (function(){ return "OK"; }).bind(this)
とほぼ同等である。bind されているに等しいことに注意。
追記:
これは利点でもある。
var obj = { threshold: 3, getOverThreshold: function (items) { return items.filter(n => n > this.threshold); }, /* 下記のような var self = this が必要ない getOverThreshold: function (items) { var self = this; return items.filter(function(n){ return n > self.threshold; }); }, */ };
即時関数
(function(global) { "use strict"; global === window; // ブラウザ等では true global.foo = "OK"; })(this);
みたいなやつね。
(global => { // ... })(this);
this
が bind されていることを書いたが、このことはStrictモード環境であっても下記のように書けることを示す。
(() => { "use strict"; this === window; // ブラウザ等では true this.foo = "OK"; })();
関数名を付けられない
これは結構痛い。
"use strict"; var obj = { init: function () { document.body.addEventListener("click", aEvent => { document.body.removeEventListener("click", arguments.callee); this.doSomthing(); }); }, doSomething: function () { // ...処理 }, }
Strictモード環境では、arguments.callee
は使用できないので、上記コードは意図通りには動かないだろう。自身を示す関数を得る手段がなく、一回限りでイベントをとって即removeEventListener
ができない。
変数に格納してから、やれば可能ではあるが、var self = this
とやるのと大して手間が省略されていない気がする。
"use strict"; var obj = { init: function () { var onClick = aEvent => { document.body.removeEventListener("click", onClick); this.doSomething(); }; document.body.addEventListener("click", onClick); }, doSomething: function () { // ...処理 }, }
下記のようなものも失敗である。ArrorFunction 内の this
は obj
にならない。(function(){}.bind(this)
に書き直してみればわかると思う)
"use strict"; var obj = { init: function () { document.body.addEventListener("click", this.onClick); }, onClick: aEvent => { document.body.removeEventListener("click", this.onClick); this.doSomething(); }, doSomething: function () { // ...処理 }, }
まとめ(?)
function
のシンタックスシュガーではない- 名前を付けられないことに注意
- 定義時にbind(this)されているかのように振る舞うことに注意
(ネタ)Brainfuck (階乗する関数)
var factorial = ((fact=n=>n>1 ?n*fact(n-1):1)=>(fact))(); factorial(6); // 720
DefaultParameterも使用したハックであるが、普通思いつかねぇよ...。
追記
さらに試して気付いたこと。
- 強制的にStrictモード環境
- ArrowFunction オブジェクトに
prototype
プロパティが存在しない - ArrowFunction 実行時、
arguments
オブジェクトは生成されない - ArrowFunction は
[[construct]]
を持たないはずなのでnew
できるべきでない(Bug 848197)