2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおけるthisの挙動と設計的制御:呼び出し元に依存する文脈と明示的バインディングの技法

Posted at

概要

JavaScriptの this“関数がどこで定義されたか”ではなく、“どう呼び出されたか”に依存して決まる
これは柔軟性を提供する反面、開発者の混乱とバグの温床になりやすい。

本稿では以下を徹底整理する:

  • this の文脈による挙動パターン
  • アロー関数による束縛とその限界
  • bind, call, apply の使い分け
  • クラス内メソッドとthisの一貫性
  • thisを意図通りに設計するための実用的戦略

1. グローバル文脈での this

console.log(this); // ブラウザ → window / Node.js → global
  • 関数呼び出しではグローバルに束縛される(非strictモード)
  • strict mode では this === undefined
'use strict';
function f() {
  console.log(this); // undefined
}

2. メソッド呼び出しと this

const obj = {
  name: 'Toto',
  say() {
    console.log(this.name);
  }
};

obj.say(); // 'Toto'

→ ✅ thisobj を参照(呼び出し元がobj)


3. 代入やコールバックでthisが失われるケース

const fn = obj.say;
fn(); // ❌ undefined(グローバルthis)

→ ✅ this を失う → bind で固定する必要がある


4. bind, call, apply による明示的バインディング

const bound = obj.say.bind(obj);
bound(); // ✅ 'Toto'

obj.say.call({ name: 'Alice' }); // 'Alice'
obj.say.apply({ name: 'Bob' });  // 'Bob'
メソッド 意味 引数の渡し方
bind this を束縛して関数を返す 事前定義
call その場で実行、this指定 func.call(this, a, b)
apply その場で実行、this指定 func.apply(this, [a, b])

5. アロー関数における this の束縛

const obj = {
  name: 'Toto',
  say: () => {
    console.log(this.name); // ❌ undefined
  }
};

obj.say(); // ❌ 'this'はobjではなくグローバルを参照
  • ✅ アロー関数は this を“レキシカルに束縛”する
  • ✅ 親スコープの this を引き継ぐ
  • ❌ オブジェクトメソッドでは非推奨

6. クラスにおける this とbindの必要性

class Button {
  constructor(label) {
    this.label = label;
    this.handleClick = this.handleClick.bind(this); // ✅
  }

  handleClick() {
    console.log(`${this.label} clicked`);
  }
}

→ ✅ イベントリスナーなど、外部で呼び出される関数にはbindが必須


7. よくあるthisのバグと防御策

❌ イベントハンドラで this がずれる

element.addEventListener('click', obj.say); // ❌ this is not obj

→ ✅ obj.say.bind(obj) を渡す


❌ setTimeout や Promiseチェーンで this を失う

setTimeout(obj.say, 1000); // ❌

setTimeout(() => obj.say(), 1000); // ✅ アロー関数で文脈保持

設計判断フロー

① this を“呼び出し元に依存させたい”? → 通常の function

② this を“常に固定”したい? → bind を使う

③ this を“親スコープに追従”させたい? → アロー関数

④ コールバック・イベントで this を使う? → bind か ラップ関数で固定

⑤ クラスメソッドを外部に渡す? → constructorでbind

結語

this は単なる参照ではない。
それは 関数が“どこで”ではなく、“どう”呼ばれたかに意味を持たせる構文的文脈である。

  • アロー関数は束縛のための簡潔な文法
  • bind/call/applyは明示的な意思の表現
  • this の誤用は“意図のズレ”から始まる

thisを制御するとは、関数の責務と文脈を設計することである。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?