18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Make ITAdvent Calendar 2018

Day 5

アロー関数のthisを束縛しないの意味とは

Last updated at Posted at 2018-12-04

#まえがき

おはようございます。Make IT アドベントカレンダーの5日目を担当しますバンドリが好きなhaduki1208です。
明日は @yamato3310 さんが投稿してくださいます。
明後日はライブを見に現地へ行きます。

本日の内容はJavaScriptのアロー関数の束縛の意味について自分の考えを述べます。

#thisを束縛しない?

MDN アロー関数 2018年12月04日現在

アロー関数式 は、その名のとおり矢印を使って記述し、function 式より短い構文で同様な内容を記述することができます。なおthis, arguments, super, new.target を束縛しません。また、アロー関数式は、メソッドでない関数に最適で、コンストラクタとして使うことはできません。

先日、後輩にアロー関数について質問されました。
「アロー関数はthisを束縛しない」とはどんな意味でしょうか。
僕も初めてアロー関数について学んだ際は「束縛」の意味が理解できませんでした。
今回は個人的な解釈のもと(言語仕様書をkwskは読んでないため)説明します。

※strictモードについては触れません

#束縛しないとは、強制的な値の代入を行わないということ

以下はthisの値が変わる例です。

const Human = function (name) {
    console.log(this); // (1) Human
    this.name = name;
    this.sayName = function () {
        console.log(this); // (2) Human
        console.log(`I am ${this.name}.`);
    }
    this.sayNameLater = function (time) {
        setTimeout(function () {
            console.log(this); // (3) window
            console.log(`I am ${this.name}.`);
        }, time);
    }
}
const taro = new Human("taro");
taro.sayName();
taro.sayNameLater(1000);

(1)と(2)のthisにはHumanオブジェクトが入ります。
しかし、(3)にはwindowオブジェクトが入ります

(1)はコンストラクタ(new)に呼び出されたため、thisにはHumanが代入されました。
(2)はHumanオブジェクトのインスタンスに呼び出されたため、thisにはHumanが代入されました。
(3)はグローバルから関数として呼び出されたため、thisにはwindowが代入されました。

このようにthisは呼び出し元によって値が変動します。
関数オブジェクトの呼び出し方によって定められた値が、強制的にthisに代入されるためです。

アロー関数はこの強制的な代入を行わないようにします。

まとめ
「thisを束縛する」  === 「thisに強制的に値を代入する」
「thisを束縛しない」 === 「thisに強制的に値を代入をしない」

#外のスコープのthisを参照する

アロー関数を使用する場合、thisに値は代入されません。

const taro = {
    name: "taro",
    sayName: () => {
        console.log(`I am ${this.name}.`);
    }
};
taro.sayName();

console.log(this); // window

「sayNameメソッドをアロー関数で定義した場合、thisには何も入らないからundefinedでエラーが起きる!」
って訳ではないです。外のスコープにthisがないか探してくれます。
これはグローバル領域のthis(windowオブジェクト)を参照します。

※functionを全部アロー関数に置き換えてやるぜ!って時に上のような書き方をしてバグらせてました。

const Human = function(name){
    this.name = name;
    this.sayName = () => {
        console.log(this.name);
    };
}
const taro = new Human("taro");
taro.sayName();

これは太郎君が名前をしゃべってくれます。
アロー関数の外のスコープ(Humanスコープ)は、コンストラクタによってthisにHumanが代入されているためです。

#アロー関数をコンストラクタに使用できない訳

const Human = name => {
    this.name = name;
    this.sayName = () => {
        console.log(this.name);
    };
}
const taro = new Human("taro");

「Human is not a constructor.」と怒られました。
アロー関数はthisに値を代入しないので、thisにHumanが強制的に代入されません。
thisがwindowオブジェクトのためコンストラクタの役割が成立しないからです。

#あとがき
MDNで「束縛する」「束縛しない」のキーワードはころころ変わってしまっているそうで、
アロー関数を勉強した時期によって様々な見解がありそうです。

この「thisに強制的に値を代入しない」という考え方でアロー関数に理解を深めていただけたのであれば幸いです。

18
6
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
18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?