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 内の thisobj にならない。(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 (階乗する関数)

ES-discuss より

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)