【JavaScriptのthis】メソッド、通常の関数、アロー関数の振る舞いの違い

この記事ではJavaScriptの『this』について、

  • アロー関数と通常の関数ではthisの挙動が異なること
    • オブジェクトのメソッドでthisを使用する場合の振る舞い
    • 通常の関数でthisを使用する場合の振る舞い
    • アロー関数でthisを使用する場合の振る舞い

などをサンプルコードを用いて分かりやすく説明するように心掛けています。ご参考になれば幸いです。

アロー関数と通常の関数ではthisの挙動が異なる

JavaScriptのthisは、メソッド、通常の関数、アロー関数では振る舞いが異なります。以下にそれぞれの振る舞いを簡単に説明します。

  • オブジェクトのメソッドでthisを使用する場合
    • オブジェクトのメソッドでthisを使用した場合、thisはそのメソッドが属するオブジェクトを指します。
    • メソッドがそのオブジェクトのプロパティや他のメソッドにアクセスする場合に便利です。
  • 通常の関数でthisを使用する場合
    • 通常の関数でthisを使用した場合、thisはグローバルオブジェクト(ブラウザではwindowオブジェクト、Node.jsではglobalオブジェクト)を指します。
    • JavaScriptのstrictモードではthisはグローバルオブジェクトを指さずにundefinedになります。
  • アロー関数でthisを使用する場合
    • アロー関数でthisを使用した場合、thisは外側の通常の関数から見たthisを参照します。
    • イベントハンドラやコールバック関数内で外側のthisを利用したい場合に便利です。

では実際にサンプルコードでthisの振る舞いを確認してみましょう。

オブジェクトのメソッドでthisを使用する場合

オブジェクトのメソッドでthisを使用した場合のサンプルコードを以下に示しています。

const person = {
  name: 'Taro',
  method: function () {
    console.log(this);
  },
};

person.method();
// ログ出力
// {name: 'Taro', method: ƒ}

上記のサンプルコードにおいて、methodpersonオブジェクトのメソッドであり、thisを出力する処理を記述しています。

オブジェクトのメソッドでthisを使用した場合、thisはそのメソッドが属するオブジェクト(ここではpersonオブジェクト)を指します。そのため、person.method()を実行すると、personオブジェクトの内容が出力されます。

通常の関数でthisを使用する場合

通常の関数でthisを使用した場合のサンプルコードを以下に示しています。

function regularFunction() {
  console.log(this);
}

regularFunction();
// ログ出力
// グローバルオブジェクト(ブラウザではwindowオブジェクト、Node.jsではglobalオブジェクト)が出力される

上記のサンプルコードにおいて、regularFunctionは通常の関数であり、thisを出力する処理を記述しています。

通常の関数でthisを使用した場合、thisはグローバルオブジェクト(ブラウザではwindowオブジェクト、Node.jsではglobalオブジェクト)を指します。そのため、regularFunction()を実行すると、グローバルオブジェクトが出力されます。

また、以下のサンプルコードに示すように、メソッド内に通常の関数を定義し、メソッド内にある通常の関数内でthisを出力する処理を記述した場合にも、thisはグローバルオブジェクトを指します。そのため、以下のサンプルコードでperson.method()を実行すると、グローバルオブジェクトが出力されます。

const person = {
  name: 'Taro',
  method: function () {
    function regularFunction() {
      console.log(this);
    }
    regularFunction();
  },
};

person.method();
// ログ出力
// グローバルオブジェクト(ブラウザではwindowオブジェクト、Node.jsではglobalオブジェクト)が出力される

通常の関数でthisを使用する場合(strictモードの場合)

JavaScriptにはstrictモードがあります(strictモードを有効にするには'use strict'をコードの冒頭に書きます)。strictモードの場合、thisはグローバルオブジェクトを指さずにundefinedになります。以下にサンプルコードを示します。

'use strict';
function regularFunction() {
  console.log(this);
}

regularFunction();
// ログ出力
// undefined

アロー関数でthisを使用する場合

アロー関数でthisを使用した場合のサンプルコードを以下に示しています。

// ---サンプルコード1(オブジェクト内のアロー関数)---
const person = {
  name: 'Taro',
  method: () => {
    console.log(this);
  },
};
person.method();
// ログ出力
// 外側の通常の関数から見たthisを参照する
// 上記のサンプルコードの場合、外側の通常の関数がないので、
// グローバルオブジェクト(ブラウザではwindowオブジェクト、Node.jsではglobalオブジェクト)が出力される


// ---サンプルコード2(グローバルスコープのアロー関数)---
const arrowFunction = () => {
  console.log(this);
};
arrowFunction();
// ログ出力
// 外側の通常の関数から見たthisを参照する
// 上記のサンプルコードの場合、外側の通常の関数がないので、
// グローバルオブジェクト(ブラウザではwindowオブジェクト、Node.jsではglobalオブジェクト)が出力される


// ---サンプルコード3(メソッド内のアロー関数)---
const personSub = {
  name: 'Taro',
  method: function () {
    const arrowFunction = () => {
      console.log(this);
    };
    arrowFunction();
  },
};
personSub.method();
// ログ出力
// 外側の通常の関数から見たthisを参照する
// 上記のサンプルコードの場合、外側の通常の関数から見たthisはpersonSubオブジェクトなので、
// {name: 'Taro', method: ƒ}が出力される

「サンプルコード1(オブジェクト内のアロー関数)」の解説

methodでは、thisを出力する処理をアロー関数で記述しており、このthisは外側の通常の関数から見たthisを参照しています。サンプルコード1では、外側の関数がないので、グローバルオブジェクト(ブラウザではwindowオブジェクト、Node.jsではglobalオブジェクト)が出力されます。

「サンプルコード2(グローバルスコープのアロー関数)」の解説

arrowFunctionでは、thisを出力する処理をアロー関数で記述しており、このthisは外側の通常の関数から見たthisを参照しています。サンプルコード2では、外側の関数がないので、グローバルオブジェクト(ブラウザではwindowオブジェクト、Node.jsではglobalオブジェクト)が出力されます。

「サンプルコード3(メソッド内のアロー関数)」の解説

personSubオブジェクトでは、arrowFunctionを通常の関数(function(){...}の中)で実行しています。arrowFunctionでは、thisを出力する処理をアロー関数で記述しており、このthisは外側の通常の関数から見たthisを参照しています。サンプルコード3において、外側の関数はpersonSubオブジェクトのメソッド(personSub.method())です。メソッドのthisは、そのメソッドが属するオブジェクト(ここではpersonSubオブジェクト)を指します。そのため、personSub.method()を実行すると、personSubオブジェクトの内容が出力されます。

本記事のまとめ

この記事ではJavaScriptの『this』について、以下の内容を説明しました。

  • アロー関数と通常の関数ではthisの挙動が異なること
    • オブジェクトのメソッドでthisを使用する場合の振る舞い
    • 通常の関数でthisを使用する場合の振る舞い
    • アロー関数でthisを使用する場合の振る舞い

お読み頂きありがとうございました。