Open1

【久々に触れると忘れる/備忘録】定義方法と呼び出し方で変化するthis(TypeScript)

tech_mwtech_mw

JavaScript / TypeScript の this は、「定義方法」と「呼び出し方」の2軸で参照先が変化します。
ざっくりとでも思い出せるよう、備忘録としてまとめました。

意味
① 定義方法 通常関数 or アロー関数
② 呼び出し方 直接呼び出し or ドット演算子呼び出し

1. 通常関数定義:直接呼び出し/ドット演算子による呼び出し

function で定義した関数は、呼び出し方によって this が動的に決まるという特徴があります。

  • オブジェクト経由で呼び出す → そのオブジェクトが this
  • 直接呼び出す → strictモードなら undefined、非strictモードなら window
function greet() {
  console.log(this); // A: userオブジェクト / B: undefined
  console.log(this.name); // A: "Tasuke" / B: TypeError
}

const user = {
  name: "Tasuke",
  greet,
};

user.greet();
// ドット演算子で呼び出したため this は user

greet("B");
// オブジェクトを経由しない直接呼び出し。
// strict:true → this = undefined(TypeError)
// strict:false → this = window

💡 ポイント
通常関数は「呼び出し時」に this が動的に決定される。
そのため、どこから呼び出すかによって結果が変化する。


2. オブジェクト内関数内アロー関数:ドット演算子による呼び出し

次は、関数の中でアロー関数を使うケースです。
アロー関数は 自分の this を持たず、外側の this を引き継ぐ 特性があります。

const obj1 = {
  name: "Yuki",
  start() {
    console.log(this);         // obj1
    console.log(this.name);    // "Yuki"
    const fn = () => console.log(this.name);
    fn(); // アロー関数は外側(start)の this = obj1 を引き継ぐ
  },
};

obj1.start();

💡 ポイント
アロー関数は「定義時の this」を固定(動的ではない)。
この例では、外側の start() の this が obj1 のため、内部のアロー関数も obj1 を参照。


3. オブジェクト内関数 + アロー関数:ドット演算子による呼び出し

最後は、同じオブジェクト内で function とアロー関数を比較してみましょう。
両者の違いが最も明確に現れます。

const obj2 = {
  name: "Rika",
  show1: function() {
    console.log(this);      // obj2
    console.log(this.name); // "Rika"
  },
  show2: () => {
    console.log(this); // window
    // アロー関数は this を持たないため、
    // 定義時スコープ(ブラウザでは window)を参照。
    console.log(this.name);
    // window.name(初期値は空文字)を参照するため、TypeError にはならない。
  },
};

obj2.show1();
obj2.show2(); // show2 はアロー関数のため、this は obj2 ではなく window を参照。

💡 ポイント
通常関数 → 呼び出し元オブジェクトにバインドされる
アロー関数 → 定義時スコープに固定される(ブラウザでは window)


まとめ:this のルール一覧

定義方法 呼び出し方 this の参照先
通常関数 ドット演算子 呼び出し元オブジェクト
通常関数 直接呼び出し undefined(Strict) / window(非Strict)
アロー関数 すべての呼び出し方 定義時スコープ(外側の this を参照)
関数内アロー関数 ドット演算子 外側関数の this を引き継ぐ

覚え方

種類 this の決定タイミング 性質
function 呼び出し時に決まる 🔄 動的(呼び出し元に依存)
アロー関数 定義時に決まる 🧭 静的(外側スコープを固定)