2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

`this` を完全に理解する:JavaScriptの呼び出しコンテキスト全パターン整理

Posted at

概要

this は JavaScript最大の罠とも言われる。
なぜならその挙動は、“関数の中身”ではなく、“関数の呼ばれ方”で決まるからだ。

this の正体を見極めるには、呼び出しコンテキストとバインディングのルールを体系的に理解する必要がある。
この記事では、JavaScriptにおける this の動的バインディングのルールと、それに対応するコード設計を構造的に解説する。


対象環境

ES5〜ES2023対応のJavaScript環境(Node.js / ブラウザ)

this の正体:“呼び出し元のコンテキスト”を参照する特殊キーワード

  • 実行時に動的に決定される
  • 関数の宣言時ではなく、呼び出し時に決まる
  • this の中身は、「誰が呼び出したか」によって変化する

呼び出しパターン別 this の挙動一覧

呼び出し方 this の参照先
通常の関数呼び出し(非 strict) グローバルオブジェクト(window / global
通常の関数呼び出し(strictモード) undefined
メソッド呼び出し メソッドの所有オブジェクト
コンストラクタ(new)呼び出し 新しく生成されたインスタンスオブジェクト
明示的バインド(call / apply 第一引数で指定したオブジェクト
永続バインド(bind bind() で指定されたオブジェクト
イベントリスナー(DOM) イベント発火元のDOM要素
アロー関数 外側スコープの this を継承
クラスメソッド(通常) インスタンス
クラスの静的メソッド クラス自身

各パターンを実例で確認

✅ 通常関数(非strict)

function show() {
  console.log(this); // グローバル(window / global)
}
show();

✅ strictモード下

'use strict';
function show() {
  console.log(this); // undefined
}
show();

✅ メソッドとして呼び出す

const obj = {
  name: 'Alice',
  greet() {
    console.log(this.name); // 'Alice'
  }
};
obj.greet();

✅ アロー関数

const obj = {
  name: 'Alice',
  greet: () => {
    console.log(this.name); // undefined(外側の this → グローバル)
  }
};
obj.greet();

→ アロー関数は this を自動的に閉じ込める(レキシカルスコープ)


✅ イベントリスナー内の this

button.addEventListener('click', function () {
  console.log(this); // クリックされたボタン要素
});

→ ただし、アロー関数で書くと this が変わる:

button.addEventListener('click', () => {
  console.log(this); // 外側の this(=window or undefined)
});

call, apply, bind による明示的指定

function show() {
  console.log(this.name);
}
const user = { name: 'toto' };

show.call(user); // 'toto'
show.apply(user); // 'toto'
const bound = show.bind(user);
bound(); // 'toto'

✅ コンストラクタでの this

function User(name) {
  this.name = name;
}
const u = new User('toto');
console.log(u.name); // 'toto'

✅ クラスメソッドでの this

class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    console.log(this.name);
  }
}
const p = new Person('toto');
p.greet(); // 'toto'

よくあるバグパターンと対策

❌ this が undefined / 意図外になる

const obj = {
  count: 0,
  increment() {
    setTimeout(function () {
      this.count++;
    }, 100);
  }
};

→ ✅ 対策:アロー関数 or bind(this)

setTimeout(() => {
  this.count++; // 外側の this を使う
}, 100);

this 設計の原則

シーン 推奨する this 設計
コールバック関数 アロー関数でスコープを固定
コンストラクタ / クラス 通常の関数(thisを使う)
状態を閉じ込めたい関数 アロー関数を使わずクロージャで管理
イベントリスナー function + bind(this) or クラスで管理
ライブラリ間の橋渡し call / apply で明示的に指定

結語

this は魔法ではない。
それは、「どこから呼ばれたのか」という文脈(コンテキスト)そのものだ。

thisを理解するとは、「関数が、誰に責任を持って処理を行っているのか」を理解することでもある。
関数の本質は処理ではない。責任の構造である。

すべての this を意図して使う。
それこそが、JavaScriptを“制御できる”状態の第一歩だ。

2
3
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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?