JavaScriptのオブジェクトで使うthisキーワードをマスターしよう
生徒
「JavaScriptのオブジェクトで、thisってよく見かけるんですが、これって何ですか?」
先生
「thisは『このオブジェクト自身を指す』ための特別なキーワードです。使い方をしっかり理解すれば、オブジェクトをもっと便利に扱えますよ。」
生徒
「初心者にはちょっと難しそうですが、どうやって使うんですか?」
先生
「大丈夫、ゆっくり順番に見ていきましょう!」
1. thisとは何か?
JavaScriptのthisは、「今実行している関数がどのオブジェクトに属しているか」を指します。オブジェクトの中で使えば、そのオブジェクト自身を表します。
イメージとしては、「自分自身を指さす矢印」のようなものです。
2. オブジェクト内メソッドでのthis
オブジェクトの中にある関数(メソッド)の中でthisを使うと、そのオブジェクトを指します。
const user = {
name: "花子",
greet() {
console.log(this.name + "さん、こんにちは!");
}
};
ここでuser.greet()を実行すると、 thisがuserを指し、名前を使ってあいさつできます。
花子さん、こんにちは!
3. thisの使い道と注意点
オブジェクトのプロパティを使って計算したり、別のメソッドを呼び出すときにthisが便利です。
const counter = {
count: 0,
increment() {
this.count++;
}
};
counter.increment();
console.log(counter.count); // 1
ここではthis.countを使うことで、自分のカウント値を増やしています。
4. thisがundefinedになるケース
注意したいのは、関数だけを取り出して呼ぶと、thisが期待したオブジェクトではなくundefinedになります。
const fn = user.greet;
fn(); // thisがuser以外を指してundefinedになる
このようなときは、.bind()やアロー関数で対応できます。
5. bindを使ってthisを固定する
.bind()メソッドを使えば、関数の中でthisを指定したオブジェクトに固定できます。
const boundGreet = user.greet.bind(user);
boundGreet(); // userを指して正しくあいさつできる
6. アロー関数とthis
アロー関数はthisを外側のスコープから引き継ぎます。オブジェクト内でアロー関数を使うとthisが別のオブジェクトを指すので、注意が必要です。
const obj = {
value: 10,
show: () => {
console.log(this.value); // undefinedになる
}
};
obj.show();
メソッドでは普通の関数を使いましょう。
7. thisを使う場面は?
- オブジェクトのプロパティを安全に参照したいとき
- メソッド同士で情報をやり取りしたいとき
- イベントやコールバックで呼ばれる関数でも
thisが指すものをコントロールしたいとき
初心者のうちは、まず「オブジェクトの中ではthis=そのオブジェクト」と覚えておくと良いでしょう。
まとめ
ここまでJavaScriptにおけるthisキーワードの基本的な仕組みから、実践的な使い方、そして初心者が陥りやすい注意点について詳しく解説してきました。thisは一見すると非常に複雑で、実行されるコンテキスト(文脈)によって指し示す内容が変化するという性質を持っています。しかし、その本質を理解してしまえば、オブジェクト指向的なプログラミングを行う上でこれほど強力な味方はありません。
thisの本質とオブジェクトの結びつき
JavaScriptを学び始めたばかりの頃は、「なぜ直接変数名を使わずにthisを使うのか?」という疑問を抱くかもしれません。その答えは、コードの再利用性と柔軟性にあります。例えば、同じ構造を持つ複数のオブジェクトを扱う際、thisを利用することで、関数を特定のオブジェクト名に依存させることなく記述できます。これにより、動的に生成されたオブジェクトに対しても、共通のメソッドを安全に適用させることが可能になるのです。
改めて整理すると、thisの基本的な挙動は以下の4つのルールに集約されます。
- メソッド呼び出し:
obj.method()のように呼び出された場合、thisはそのオブジェクト(obj)を指します。 - 関数呼び出し: 単なる関数として呼び出されると、
thisはグローバルオブジェクト(ブラウザならwindow、strictモードならundefined)を指します。 - コンストラクタ呼び出し:
newキーワードを使ってインスタンスを生成する場合、thisは新しく作られたインスタンスを指します。 - 明示的なバインド:
call、apply、bindを使うことで、開発者が意図的にthisを決定できます。
実践的なコード例:複数のオブジェクトでメソッドを共有する
thisの便利さを実感するために、複数のキャラクターが共通の攻撃アクションを持つような簡単なプログラムを考えてみましょう。
function attack() {
console.log(this.name + "は、" + this.weapon + "で攻撃した!");
}
const warrior = {
name: "戦士",
weapon: "鋼の剣",
doAction: attack
};
const mage = {
name: "魔法使い",
weapon: "炎の杖",
doAction: attack
};
warrior.doAction();
mage.doAction();
このコードの実行結果は以下のようになります。
戦士は、鋼の剣で攻撃した!
魔法使いは、炎の杖で攻撃した!
このように、attackという関数は一つだけですが、呼び出し元のオブジェクトに応じてthis.nameやthis.weaponの内容が切り替わります。これがthisの持つ大きなメリットです。
よくあるエラーの回避策
記事の本編でも触れた通り、コールバック関数の中でthisを見失うケースは非常に多いです。例えば、タイマー処理(setTimeout)やイベントリスナーの中でオブジェクトのメソッドを呼び出すと、thisが予期せぬものを指してしまいます。これを解決するのがbindメソッドやアロー関数です。
最近のモダンなJavaScript開発(ReactやVue.jsなどのフレームワークを含む)では、thisの挙動が予測しやすいアロー関数をあえて使う場面と、オブジェクトのメソッドとして従来の関数を使う場面を使い分けるのが一般的です。
生徒
「先生、ありがとうございました。thisについて色々と分かりました!結局、thisは『誰がその関数を呼んでいるのか』を見ればいいんですね?」
先生
「その通りです!素晴らしい気づきですね。ドット(.)の左側にあるオブジェクトが、基本的にはthisの正体だと思えば間違いありません。例えばuser.greet()なら、ドットの左のuserがthisになります。」
生徒
「なるほど。でも、アロー関数のときはそのルールが通用しないんですよね。そこが少しややこしいです……。」
先生
「そうですね。アロー関数は自分自身のthisを持たず、外側の世界のthisをそのまま持ってくるという特殊な性質があります。だから、オブジェクトのメソッドを定義するときにアロー関数を使ってしまうと、外側のグローバルな世界を見に行ってしまって、結果的にundefinedになってしまうんです。」
生徒
「使い分けが大事ですね。メソッドは普通の関数で書いて、その中の細かい処理やコールバックで外のthisを維持したいときはアロー関数を使う、という感じでしょうか?」
先生
「完璧な理解です!その使い分けができれば、もう初心者卒業と言ってもいいでしょう。最初は混乱するかもしれませんが、実際にコードを書いてみて、コンソールにconsole.log(this)を表示させて中身を確認する癖をつけると、どんどん感覚が掴めてきますよ。」
生徒
「まずはデバッグでthisの中身を覗くところから始めてみます!ありがとうございました!」