bind, call, applyメソッドの使用 | thisの扱い方 | JavaScript 超完全入門 基本から発展までのすべて

スポンサーリンク
スポンサーリンク
amazon
スマイルSALE
--:--:--
ad. 価格範囲を指定して商品を探せます

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.greetpersonへバインドした新しい関数を作成しています。

  1. bind()で新しい関数を作成します。
  2. 新しい関数ではthisが常にpersonになります。
  3. あとから実行しても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を書ける。