this の束縛差とは何か
this は「関数が“どのオブジェクトを対象に動くか”を指す特別な値」です。ここが重要です:従来の function は“呼び出し方”で this が決まり、アロー関数は“定義場所の this(レキシカル this)”に固定されます。この差を理解すると、イベントや非同期コールバックでの「this 迷子」を防げます。
従来の function の this(呼び出し方で決まる)
メソッド呼び出し(obj.method())
obj.method() のように“ドット左”のオブジェクトが this になります。
const counter = {
value: 0,
inc: function() { this.value++; }
};
counter.inc();
console.log(counter.value); // 1(this は counter)
JavaScript単独呼び出し(関数をただ呼ぶ)
関数をそのまま呼ぶと、strict モードでは this は undefined、非 strict ではグローバル(window)になります。ここが重要です:strict を前提にして undefined になる設計にするのが安全です。
"use strict";
function f() { console.log(this); }
f(); // undefined(strict)
JavaScriptコンストラクタ呼び出し(new)
new で呼ぶと、this は“新しいインスタンス”になります。
function User(name) { this.name = name; }
const u = new User("Alice");
console.log(u.name); // "Alice"
JavaScript明示束縛(call / apply / bind)
this を手動で指定できます。bind は“this 固定の新関数”を返します。
function show() { console.log(this.id); }
const obj = { id: 123 };
show.call(obj); // 123
const bound = show.bind(obj);
bound(); // 123(常に obj)
JavaScriptアロー関数の this(レキシカルに“固定”)
定義場所の this をキャプチャする
アロー関数は“自分自身の this を持たず”、外側の this をそのまま使います。ここが重要です:クラス内でコールバックにすると、bind なしで意図通りに動きます。
class Counter {
constructor() {
this.value = 0;
setInterval(() => { this.value++; }, 1000); // this はクラスのインスタンス
}
}
JavaScriptメソッド定義には不向き
オブジェクトのメソッドで this を“呼び出し方に合わせたい”なら、function 記法を使います。アローだと外側の this を掴んでしまい、obj を指さなくなります。
const obj = {
x: 0,
inc() { this.x++; } // 正しい(this は obj)
// inc: () => { this.x++; } // NG(外側の this を参照)
};
JavaScriptよくある this 迷子と解決策(重要ポイントの深掘り)
メソッドを変数に取り出して呼ぶと失敗
メソッドを取り出すと“ドット左”が失われ、this が undefined になります。bind か、アローのコールバックで包んで回避します。
"use strict";
const obj = { id: 1, show() { console.log(this.id); } };
const fn = obj.show;
// fn(); // TypeError(this が undefined)
const bound = obj.show.bind(obj);
bound(); // 1(bind で固定)
// またはコールバック内でレキシカル this を使う
setTimeout(() => obj.show(), 0); // 1
JavaScriptイベントハンドラでの this
DOM の addEventListener のコールバックにおける this は“イベントの currentTarget”ではなく、strict では undefined です。必要なら event.currentTarget を使い、this 目当てで書かないのが安全です。
button.addEventListener("click", function (e) {
console.log(e.currentTarget === button); // true
});
button.addEventListener("click", (e) => {
console.log(e.currentTarget.id); // アローでも e を使えば安全
});
JavaScriptsetTimeout / Promise での this 破綻
function を直接渡すと this が失われがち。アロー関数にして外側の this を固定するか、bind で固定します。
const view = {
id: 42,
render() { console.log(this.id); }
};
// 失敗例
setTimeout(view.render, 0); // TypeError(this なし)
// 解決(アローで包む)
setTimeout(() => view.render(), 0); // 42
// もしくは bind
setTimeout(view.render.bind(view), 0); // 42
JavaScript実務での指針(いつアロー、いつ function)
コールバックはアロー、メソッドは function
非同期・配列処理・イベント登録など“外側の this を使いたい”コールバックはアロー関数が最適。オブジェクトやクラスの“メソッドとして使う”関数は function 記法で定義します。
class Timer {
constructor() {
this.ticks = 0;
this.start = () => { // アロー:this 固定
this.id = setInterval(() => this.ticks++, 1000);
};
}
stop() { // メソッド:function 記法
clearInterval(this.id);
}
}
JavaScriptthis が必要ない設計を選ぶ
this 前提の API ではなく、引数ベースの純粋な関数に寄せると安全性とテスト容易性が上がります。ここが重要です:this を使わず、受け取った値を返す“純粋な処理”を増やす。
const toLabel = (user) => `${user.id}:${user.name.trim()}`; // this 不要の関数
JavaScriptまとめ
this の束縛差の核心は「function は呼び出し方で this が変わり、アロー関数は定義場所の this に固定される」ことです。メソッド抽出・非同期コールバック・イベント登録で this が失われやすい箇所は、アローで外側の this をキャプチャするか bind で固定する。メソッドは function 記法、コールバックはアロー、strict モードを前提にして“this なし”を安全側にする。この指針を徹底すれば、初心者でも this で迷わず意図どおりの ES6+ コードを書けます。
