LoginSignup
10
10

More than 3 years have passed since last update.

ECMAScript 2015 のアロー関数で罠に引っかかった件

Last updated at Posted at 2016-02-01

結論

CoffeeScript みたいに this を bind するアロー関数 => と bind しない関数 -> の2つを用意してくれないと辛いと思った。
まぁ ECMAScript 的な書き方をしていないだけかもしれないけど。。。

JavaScript のモジュールの作り方

JavaScript で prototype などを使ってモジュールを作る時の書き方の一つとして次のような書き方がある。

main.js
'use strict';
function Obj (value) {
  this._value = value;
}
Obj.prototype.value = function (val) {
  if (val) {
    this._value = val;
    return this;
  } else {
    return this._value;
  }
};
Obj.prototype.setKey = function (key) {
  return { key: key, value: this.value() };
};
module.exports = Obj;

これを今回 「ECMAScript2015 ではアロー関数がある!簡潔に書ける!!」とか調子乗って使ったら見事にはまった。

this.value is not a function

今回の変更は以下の通り。 xxx = function () {}の部分をアロー関数に変換した。

main.js
'use strict';
function Obj (value) {
  this._value = value;
}
Obj.prototype.value = (val) => {
  if (val) {
    this._value = val;
    return this;
  } else {
    return this._value;
  }
};
Obj.prototype.setKey = (key) => {
  return { key: key, value: this.value() };
};
module.exports = Obj;

そしたら上の this.value is not a function を食らうはめに。。。

実は this が bind されないことで救われていた JavaScript

一応自分の中での this の理解の確認も兼ねてちょっと丁寧に説明してみる。
もし違ってたらご指摘お願いします :)

もともと js の this は「どこで定義しているか?」ではなく「誰が呼び出しているか?」によって決定する。
例えば

Obj.prototype.doMethod = function () { return this; }

というメソッドがあった時、この時点では this は決定していなくて、

var o = new Obj();
console.log(o.doMethod());

といったコードが実行された時に Obj オブジェクトのインスタンスが doMethod を実行してるから、結果として Obj に紐付いているように見える。

しかし、今回のアロー関数を使う事で(内部的にどう変換されているのかはキチンと把握していないですが。。。)以下のようなコードを書いている事と同義になる。

Obj.prototype.doMethod = (function () {
  return this;
}).bind(this);

この bind メソッドによって関数内部の this が1段上のスコープに存在する this と紐付けられる。

ということで this が Obj ではなく global に紐付けられてもうた。。。

this を bind しないアロー関数がほしいです先生。

10
10
5

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
10
10