概要
JavaScriptにおける this
は「オブジェクト自身」ではない。
それは**“関数がどの文脈(コンテキスト)で呼び出されたかによって変化する、動的な参照ポイント”**である。
this
の挙動を曖昧なまま放置すると、予期しないバグや参照エラー、設計意図の崩壊を引き起こす。
逆に、this
を設計的に制御できれば、クラス設計・イベント処理・コールバックの明確化が可能となる。
本稿では、this
の挙動パターン・制御方法・設計戦略を体系的に整理する。
1. グローバル文脈での this
console.log(this); // ✅ window(ブラウザ) / global(Node.js)
- ✅ グローバルでは
this
はトップレベルオブジェクトを指す - ❌ 厳格モード (
'use strict'
) ではundefined
になる
2. オブジェクトメソッド内の this
const obj = {
name: 'Taro',
greet() {
console.log(this.name);
}
};
obj.greet(); // ✅ 'Taro'
- ✅
this
は「呼び出し元オブジェクト」を指す - ❌ 代入・分離された場合に文脈が失われる:
const greet = obj.greet;
greet(); // ❌ undefined(グローバルの this)
3. アロー関数における this
const obj = {
name: 'Taro',
greet: () => {
console.log(this.name);
}
};
obj.greet(); // ❌ undefined(アロー関数は this を持たない)
- ✅ アロー関数は定義時の this をレキシカルに保持
- ❌ オブジェクトメソッドには不適切 → 通常関数で書くべき
4. bind
/ call
/ apply
による明示的バインド
function say() {
console.log(this.word);
}
const ctx = { word: 'Hello' };
say.call(ctx); // ✅ 'Hello'
say.apply(ctx); // ✅ 'Hello'
say.bind(ctx)(); // ✅ 'Hello'
- ✅ 動的に文脈を切り替えて
this
を制御 - ✅ イベントハンドラやユーティリティ関数での活用に適す
5. クラスと this
:コンストラクタとメソッドの文脈保持
class Greeter {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hi, I'm ${this.name}`);
}
}
- ✅ クラス内メソッドの
this
は常にそのインスタンスを指す - ❌ コールバック等に渡す場合、
bind
しないとthis
が失われる
const g = new Greeter('Jiro');
setTimeout(g.greet, 100); // ❌ thisが失われる
setTimeout(g.greet.bind(g), 100); // ✅ 明示的バインド
設計判断フロー
① この関数が呼び出される文脈は明確か?(オブジェクト / グローバル / クラス)
② コールバックで this が失われていないか? → bind / アロー関数を検討
③ オブジェクトのメソッドにアロー関数を使っていないか?
④ イベントハンドラの中の this に依存していないか?(document.addEventListener 等)
⑤ クラスメソッドをバインドせずに外部に渡していないか?
よくあるミスと対策
❌ アロー関数内で this に依存した処理
→ ✅ 通常の function を使う / コンテキストを引数で渡す
❌ クラスメソッドを setTimeout や addEventListener に渡して this が消失
→ ✅ 事前に bind(this)
する or アロー関数でラップする
❌ メソッドを取り出して他のコンテキストで使い this が破綻
→ ✅ 関数を切り出すときは bind()
で設計意図を固定化する
結語
JavaScriptの this
は「オブジェクト自身」ではない。
それは**“文脈に応じて動的に変化する参照であり、設計者が意図的に制御すべき構造要素”**である。
-
this
を理解することは「関数の責任範囲と実行主体」を明確にすること - 設計の中で 誰が呼び出すのか、どこで使うのか、何に属しているのか を言語化する
- 文脈のバインドは、コードの読みやすさと保守性に直結する
JavaScriptにおける this
の設計とは、
“関数のアイデンティティと実行コンテキストを構造として定義する戦略である。”