【JavaScript】プログラミング初心者が抑えておくべきthisの挙動と使い方
2023年2月20日
JavaScriptのthisは、JavaScriptプログラミングにおいて非常に重要な概念の1つです。thisは、コンテキストに応じて変化する特殊なキーワードであり、関数内部で呼び出されると、その関数を呼び出すオブジェクトを参照することができます。
この記事では、thisの挙動、使用方法、およびthisの一般的な問題、call、 apply、 bind メソッドについて詳しく説明します。
thisの挙動
JavaScriptのthisは、呼び出し元のオブジェクトを参照するために使用されます。thisの値は、関数がどのように呼び出されたかによって決定されます。
具体的には、以下の4つのパターンがあります。
グローバルコンテキスト
thisがグローバルコンテキストで呼び出された場合、thisはグローバルオブジェクトを参照します。
ブラウザでは、windowオブジェクトがグローバルオブジェクトです。
Node.jsでは、globalオブジェクトがグローバルオブジェクトです。
console.log(this === window); // ブラウザ環境でtrueを返す
console.log(this === global); // Node.js環境でtrueを返す関数呼び出し
thisが関数内で呼び出され、関数がオブジェクトのプロパティである場合、thisはそのオブジェクトを参照します。
これをメソッド呼び出しと呼びます。
const person = {
name: 'john',
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
};
person.sayHello(); // "Hello, my name is john"と出力されるcallおよびapplyメソッドによる呼び出し
thisがcallまたはapplyメソッドで呼び出された場合、thisはメソッドの第1引数に渡されたオブジェクトを参照します。
これを明示的なバインディングと呼びます。
function sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
const person1 = { name: 'John' };
const person2 = { name: 'Alice' };
sayHello.call(person1); // "Hello, my name is John"と出力される
sayHello.call(person2); // "Hello, my name is Alice"と出力されるnewキーワードによる呼び出し
thisがnewキーワードで呼び出された場合、thisは新しいオブジェクトを参照します。
これをコンストラクタ呼び出しと呼びます。
class Person(name) {
this.name = name;
}
const john = new Person('John');
console.log(john.name); // "John"と出力されるthisの使用方法
thisは、オブジェクト指向プログラミングのコンテキストで非常に役立ちます。thisを使用することで、関数をオブジェクトにバインドし、そのオブジェクトのプロパティにアクセスすることができます。
メソッド呼び出し
メソッド呼び出しでは、thisを使用して、オブジェクトのプロパティにアクセスすることができます。
const person = {
name: 'John',
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
};
person.sayHello(); // "Hello, my name is John"と出力されるコンストラクタ呼び出し
コンストラクタ呼び出しでは、thisを使用して、新しいオブジェクトを作成し、そのオブジェクトのプロパティを初期化することができます。
class Person(name) {
this.name = name;
}
const john = new Person('John');
console.log(john.name); // "John"と出力される明示的なバインディング
明示的なバインディングでは、thisを使用して、関数を特定のオブジェクトにバインドし、そのオブジェクトのプロパティにアクセスすることができます。
function sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
const person1 = { name: 'John' };
const person2 = { name: 'Alice' };
sayHello.call(person1); // "Hello, my name is John"と出力される
sayHello.call(person2); // "Hello, my name is Alice"と出力されるthisの問題
thisは非常に便利なキーワードですが、混乱が生じやすい部分でもあります。
以下は、一般的なthisの問題とその解決策です。
thisの値が変わる
thisの値は、関数がどのように呼び出されたかによって変わります。
たとえば、メソッドとして定義された関数を変数に代入して呼び出した場合、thisの値はグローバルオブジェクトになります。
const person = {
name: 'John',
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
};
const sayHello = person.sayHello;
sayHello(); // "Hello, my name is undefined"と出力されるこの問題を解決するには、bind()、call()、またはapply()を使用して、thisの値を明示的に指定することができます。
const person = {
name: 'John',
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
};
const sayHello = person.sayHello.bind(person);
sayHello(); // "Hello, my name is John"と出力されるthisのスコープが変わる
thisは、オブジェクトから呼び出された関数にバインドされます。
しかし、関数がネストされた場合、thisの値は親関数のthisとは異なる値になることがあります。
const person = {
name: 'John',
sayHello() {
console.log(`Hello, my name is ${this.name}`);
function innerFunction() {
console.log(`Hello, my name is ${this.name}`);
}
innerFunction();
}
};
person.sayHello(); // "Hello, my name is John"と出力される
// "Hello, my name is undefined"と出力されるこの問題を解決するには、thisを変数に保存することができます。
これにより、内部関数でthisを使用する際に、保存した変数を参照することができます。
const person = {
name: 'John',
sayHello() {
const self = this;
console.log(`Hello, my name is ${this.name}`);
function innerFunction() {
console.log(`Hello, my name is ${self.name}`);
}
innerFunction();
}
};
person.sayHello(); // "Hello, my name is John"と出力される
// "Hello, my name is John"と出力されるまたは、ES6以降のJavaScriptでは、アロー関数を使用することで、外部関数のthisを維持することができます。
const person = {
name: 'John',
sayHello() {
console.log(`Hello, my name is ${this.name}`);
const innerFunction = () => {
console.log(`Hello, my name is ${this.name}`);
}
innerFunction();
}
};
person.sayHello(); // "Hello, my name is John"と出力される
// "Hello, my name is John"と出力される【補足】call・apply・bindメソッド
JavaScriptには、関数オブジェクトに対して call、 apply、 bind といったメソッドが用意されています。
これらのメソッドは、関数を呼び出す方法を制御するために使用されます。
call メソッド
call メソッドは、ある関数を別のオブジェクトのメソッドとして呼び出す場合に使用されます。call メソッドは、関数の最初の引数に使用する this キーワードに代入する値を指定します。
function sayHello() {
console.log(`Hello, ${this.name}!`);
}
const person = { name: 'Alice' };
sayHello.call(person); // => "Hello, Alice!"call メソッドの第2引数以降は、呼び出す関数の引数として使用されます。
function sum(a, b) {
console.log(a + b);
}
sum.call(null, 1, 2); // => 3上の例では、 sum 関数がグローバルスコープで定義されているため、null を this キーワードに指定しています。
apply メソッド
apply メソッドは、 call メソッドと似ていますが、引数を配列で渡す点が異なります。apply メソッドは、関数の最初の引数に使用する this キーワードに代入する値を指定します。
function sum(a, b) {
console.log(a + b);
}
sum.apply(null, [1, 2]); // => 3bind メソッド
bind メソッドは、関数を新しい関数として返すことができます。
返された関数は、元の関数と同じ引数と this キーワードを受け取ります。this キーワードには、 bind メソッドに渡されたオブジェクトがバインドされます。
function sayHello() {
console.log(`Hello, ${this.name}!`);
}
const person = { name: 'Alice' };
const hello = sayHello.bind(person);
hello(); // => "Hello, Alice!"また、 bind メソッドには、引数を渡すこともできます。
function sum(a, b) {
console.log(a + b);
}
const addOne = sum.bind(null, 1);
addOne(2); // => 3上の例では、 sum 関数の最初の引数に 1 を指定し、 addOne 関数を返します。addOne 関数は、引数に 2 を受け取る前に、sum関数でbindした 1 を最初の引数として受け取ります。
call、 apply、 bind の使い分け
最後にcall、apply、bindメソッドについて簡単に使い分けをまとめました。
callメソッドは、関数を呼び出す際に、関数の引数をカンマ区切りで指定し、thisキーワードを指定する。applyメソッドは、関数を呼び出す際に、引数を配列で渡し、thisキーワードを指定する。bindメソッドは、関数を新しい関数として返し、引数に値を渡すこともできる。bindメソッドを使用すると、オブジェクトに関数をバインドでき、関数を異なるオブジェクトで使用することができる。
まとめ
この記事ではthisの挙動、使用方法およびthisの一般的な問題、call、 apply、 bind メソッドについてまとめました。this は、JavaScriptにおいて重要な概念の1つであり、関数が呼び出されたときにその関数が属しているオブジェクトを参照するために使用されます。
また、this の値は、関数が呼び出される際に動的に決定されます。this は、関数がどのように呼び出されたかによって異なる値を持つことがあるので、その点は抑えておきましょう。
また当ブログでは、JavaScriptを学び始めたばかりの方や、スキルを磨きたい方に向けて、こちらのUdemy講座をおすすめしています。
Udemyでは、JavaScriptの基本から応用まで学ぶことができる講座が豊富に揃っています。
その中でもこちらの講座は非常に分かりやすく、おすすめしています。
thisの挙動についてもとても分かりやすく解説されています!

管理人
よかったらぜひチェックしてみてください。
最後まで読んでいただきありがとうございました。