INDEX
thisのバインドについて

JavaScriptでは、thisの値は関数がどのように呼び出されたかによって決まります。そのため、意図したオブジェクトをthisとして利用したい場合には、明示的にthisを指定する必要があります。
その際に利用するのが、bind()、call()、apply()の3つのメソッドです。これらは関数のthisを制御するための代表的な方法です。
なお、ES6以降ではアロー関数が普及したことでthisに関する問題は減りましたが、これら3つのメソッドは現在でも頻繁に利用されています。
bind()メソッド
bind()は、thisを固定した新しい関数を作成するメソッドです。
元の関数は実行されず、bind()は新しい関数を返します。
bind()メソッドの例
const person = {
name: "Taro",
greet() {
console.log("Hello, " + this.name);
}
};
const greetFunc = person.greet.bind(person);
greetFunc();
// Hello, Taro
この例では、person.greetをpersonへバインドした新しい関数を作成しています。
bind()で新しい関数を作成します。- 新しい関数では
thisが常にpersonになります。 - あとから実行しても
thisは変わりません。
call()メソッド
call()は、thisを指定してその場で関数を実行するメソッドです。
第1引数にthisとなるオブジェクトを指定し、その後に関数の引数を順番に渡します。
call()メソッドの例
const person1 = {
name: "Taro"
};
const person2 = {
name: "Hanako"
};
function greet() {
console.log("Hello, " + this.name);
}
greet.call(person1);
greet.call(person2);
// Hello, Taro
// Hello, Hanako
この例では、呼び出すたびにthisを変更しています。
apply()メソッド
apply()もcall()と同じように、その場で関数を実行します。
違いは、関数へ渡す引数を配列(または配列風オブジェクト)で渡すことです。
apply()メソッドの例
const person1 = {
name: "Taro"
};
const person2 = {
name: "Hanako"
};
function introduce(age, city) {
console.log(this.name + " is " + age + " years old and lives in " + city);
}
introduce.apply(person1, [25, "Tokyo"]);
introduce.apply(person2, [30, "Osaka"]);
// Taro is 25 years old and lives in Tokyo
// Hanako is 30 years old and lives in Osaka
現在では配列を展開できるスプレッド構文(...)が利用できるため、apply()を使用する場面は以前より少なくなっています。
bind()・call()・apply()の違い
| メソッド | 実行されるタイミング | 引数の渡し方 |
|---|---|---|
bind() |
実行しない(新しい関数を返す) | 通常の引数 |
call() |
すぐ実行する | 通常の引数 |
apply() |
すぐ実行する | 配列で渡す |
複数の引数を扱う例
call()とapply()は、引数の渡し方だけが異なります。
const person = {
name: "Taro"
};
function showInfo(age, city) {
console.log(this.name + " is " + age + " years old and lives in " + city);
}
showInfo.call(person, 25, "Tokyo");
showInfo.apply(person, [25, "Tokyo"]);
// Taro is 25 years old and lives in Tokyo
// Taro is 25 years old and lives in Tokyo
実行結果は同じですが、引数の渡し方が異なります。
スプレッド構文との関係
ES6以降では、apply()を使わなくてもスプレッド構文を利用して配列を展開できます。
const numbers = [3, 7, 2, 9];
console.log(Math.max(...numbers));
// 9
以前は次のようなコードがよく使われていました。
console.log(Math.max.apply(null, numbers));
// 9
現在ではスプレッド構文のほうが読みやすいため、新しくコードを書く場合はこちらが推奨されます。
初心者が知っておきたいポイント
bind()は新しい関数を返すだけで、その場では実行されない。call()とapply()はその場ですぐに関数を実行する。call()は引数を順番に渡し、apply()は配列で渡す。- 現在では配列の展開にはスプレッド構文が使われることが多い。
- アロー関数は独自の
thisを持たないため、bind()が不要になる場面も多い。
まとめ
bind()、call()、apply()はthisを明示的に指定するためのメソッドである。bind()はthisを固定した新しい関数を作成する。call()はその場で関数を実行し、引数は通常どおり渡す。apply()はその場で関数を実行し、引数を配列で渡す。- 現在ではスプレッド構文やアロー関数も併せて理解しておくと、より現代的なJavaScriptを書ける。