JavaScriptのthisと関数呼び出しの関係を初心者向けに完全解説!
生徒
「JavaScriptでよく出てくるthisって何ですか?どうやって使うんですか?」
先生
「thisは、その関数やオブジェクトがどのコンテキストで呼ばれたかによって指す対象が変わる特別なキーワードです。簡単に言うと、『今この関数の中で参照しているオブジェクト』を表します。」
生徒
「オブジェクトによって変わるってことですか?どういうときに変わるんですか?」
先生
「そうですね。関数の呼び出し方によって、thisが指すものは変わります。順番に見ていきましょう!」
1. thisとは何か?
JavaScriptのthisは、関数の中で使うと、その関数が呼ばれた状況によって指すオブジェクトが変わる特殊なキーワードです。オブジェクト指向プログラミングでは、現在のオブジェクトを参照するときに使います。基本的に、関数がどのように呼ばれたかでthisの意味が決まります。
2. グローバル関数でのthis
通常の関数をグローバルスコープで呼び出すと、thisはwindow(ブラウザ環境の場合)やglobalThisを指します。
function showThis() {
console.log(this);
}
showThis(); // ブラウザでは window が出力されます
上記の例では、showThis関数を単独で呼んでいるため、thisはグローバルオブジェクトを指します。
3. オブジェクトメソッド内のthis
オブジェクトのメソッド内でthisを使うと、そのオブジェクト自身を指します。
const person = {
name: "太郎",
greet: function() {
console.log("こんにちは、" + this.name);
}
};
person.greet(); // こんにちは、太郎
この例では、greetメソッドの中のthisはpersonオブジェクトを指しているので、nameプロパティにアクセスできます。
4. thisの値が変わるケース(関数を変数に代入)
オブジェクトのメソッドを別の変数に代入して呼ぶと、thisは元のオブジェクトを指さなくなります。
const person = {
name: "花子",
greet: function() {
console.log(this.name);
}
};
const greetFunc = person.greet;
greetFunc(); // undefined(グローバルオブジェクトに name はないため)
この場合、関数を単独で呼んでいるため、thisはグローバルオブジェクトを指すことになります。
5. call, apply, bindでthisを指定する
JavaScriptではcallやapply、bindを使うと、関数を呼び出すときにthisを任意のオブジェクトに設定できます。
function greet() {
console.log(this.name);
}
const user = { name: "次郎" };
greet.call(user); // 次郎
greet.apply(user); // 次郎
const boundGreet = greet.bind(user);
boundGreet(); // 次郎
これらを使うことで、関数の呼び出し方に関わらずthisを固定することができます。
6. アロー関数とthis
アロー関数は特殊で、自分専用のthisを持ちません。外側の関数のthisをそのまま使います。
const person = {
name: "三郎",
greet: function() {
const arrow = () => console.log(this.name);
arrow();
}
};
person.greet(); // 三郎
アロー関数内では、親のgreetメソッドのthisをそのまま参照しています。
7. 練習: 関数呼び出しによるthisの違い
下記の例でthisの挙動を確認してみましょう。
const obj = {
value: 100,
regular: function() { console.log(this.value); },
arrow: () => { console.log(this.value); }
};
obj.regular(); // 100
obj.arrow(); // undefined(グローバルオブジェクトの value は undefined)
この例では、通常関数はオブジェクト自身を参照しますが、アロー関数は外側のスコープを参照することが分かります。
8. まとめると
JavaScriptのthisは関数の呼び出し方によって指すオブジェクトが変わります。簡単に整理すると、
- グローバル関数ではグローバルオブジェクトを指す
- オブジェクトのメソッド内ではそのオブジェクト自身を指す
- 関数を変数に代入するとグローバルオブジェクトを指す
- call, apply, bindで任意のオブジェクトを指定できる
- アロー関数は自身の
thisを持たず、外側のthisを参照する
このルールを理解すると、関数呼び出しやオブジェクト操作の挙動を正しく予測できるようになります。まずは簡単な関数やオブジェクトでthisを試しながら、挙動を体験してみましょう。
まとめ
JavaScriptにおけるthisの仕組みは、プログラムの挙動を正確に理解するために欠かせない基本概念です。thisは、関数やメソッドがどのコンテキストで呼び出されたかによって指す対象が変わるため、オブジェクト指向プログラミングや関数の再利用時に重要な役割を果たします。グローバル関数でのthisはブラウザではwindow、Node.jsではglobalThisを指し、オブジェクトのメソッド内ではそのオブジェクト自身を指します。関数を変数に代入して呼ぶ場合は、thisは元のオブジェクトではなくグローバルオブジェクトを参照するため注意が必要です。
また、call、apply、bindを使うことで、関数呼び出し時に任意のオブジェクトをthisとして指定できます。これは、関数の挙動を柔軟に制御するための強力な手段です。さらに、アロー関数は独自のthisを持たず、外側のスコープのthisをそのまま使うため、コールバック関数や非同期処理でのthisの混乱を防ぐことができます。
初心者の方は、まずグローバル関数やオブジェクトメソッド、アロー関数を実際に書いてみることで、thisの挙動を体験することが理解の近道です。下記の簡単なサンプルコードで、thisがどのように変化するかを確認してみましょう。
// グローバル関数での this function showGlobalThis() { console.log(this); } showGlobalThis(); // ブラウザでは window、Node.jsでは globalThis
// オブジェクトメソッド内の this
const user = {
name: "太郎",
greet: function() {
console.log("こんにちは、" + this.name);
}
};
user.greet(); // こんにちは、太郎
// 関数を変数に代入した場合の this
const greetFunc = user.greet;
greetFunc(); // undefined(グローバルオブジェクトに name はない)
// call, apply, bind で this を指定
greetFunc.call(user); // こんにちは、太郎
greetFunc.apply(user); // こんにちは、太郎
const boundGreet = greetFunc.bind(user);
boundGreet(); // こんにちは、太郎
// アロー関数の this
const arrowUser = {
name: "花子",
greet: function() {
const arrow = () => console.log(this.name);
arrow();
}
};
arrowUser.greet(); // 花子
上記のコード例を通して、thisの指すオブジェクトがどのように変わるかを実際に確認することができます。特に、オブジェクトメソッドとアロー関数の組み合わせは、コールバック関数やイベント処理で便利に使えるパターンです。慣れるまでは、一つずつ実際にコンソールで出力を確認しながら学習することをおすすめします。
生徒
「今回のthisの内容、とてもたくさんのパターンがあって少し混乱しそうです。どこから手をつけるのがいいでしょうか?」
先生
「まずは基本のルールを押さえることが大事です。グローバル関数ではthisはグローバルオブジェクト、オブジェクトメソッド内ではそのオブジェクト自身を指す、これだけは覚えてください。」
生徒
「なるほど。それだけでもまず理解しておくと安心ですね。」
先生
「はい。その上で、関数を変数に代入した場合やcall、apply、bindの使い方を実際に試してみましょう。体験しながら学ぶと覚えやすくなります。」
生徒
「アロー関数も外側のthisを使うんですよね。これを使えば、コールバック関数の中でも安心してthisが使えるのですね。」
先生
「その通りです。アロー関数は特にイベント処理や非同期処理で威力を発揮します。まずは簡単なオブジェクトや関数で試して、出力を確認することが理解への近道です。」
生徒
「わかりました。これから実際にコードを書いて、thisの挙動を体験してみます。」
先生
「その意気です。thisを体験的に理解すると、オブジェクト指向や関数の応用がスムーズになります。焦らず、少しずつ慣れていきましょう。」