[javascript入門] call関数とbind関数、apply関数の使い方まとめ


本投稿では、call()とbind()、apply()の使い方とそれぞれの違いについて簡単にまとめます。

call()やbind()、apply()は関数をあたかもオブジェクトのメソッドであるかのように実行しちゃうことができる便利な昨日となります。

簡単に言うと、もともとの関数をなりすまして利用することができるという感じですね。

早速、それぞれの違いや使い方について説明したいと思います。

bind()について

bind()はMDN Web Docsに記載されている通りの内容だと

bindメソッドは、呼び出された際にthisキーワードに指定された値が設定される新しい関数を生成します。

と記載されています。

そもそもthisというのはなんなのかというお話しですが、簡単に説明すると

関数(function)を呼び出した時の「.(dot)」の前についているオブジェクト

という認識で良いかと思います。

function gendar(){
  console.log(this.name + " is male.");
}

var userInfo = {
  name: "kunisura",
  gendar: gendar
};

// userInfo部分がthisとなります
userInfo.gendar(); // kunisura is male.

// 下記だとthisとなるものが存在していないので「空」となります。
gendar(); // is male.

// グローバル変数を設定してみます。
window.name = "kunichan";
gendar(); // kunichan is male.

// 一度変数に代入して関数を呼び出した場合、は元のグローバルオブジェクトが参照される。
let gendar2 = userInfo.gendar;
gendar2(); // kunichan is male.

bindを利用するケースとしては、一度変数に代入して関数呼び出しを行なった場合に、グローバルオブジェクトを利用されてしまうことを避ける(呼び出し元のオブジェクトを制御)ために利用することが多いです。

let kunisuraGendar = userInfo.gendar.bind(userInfo);
kunisuraGendar(); // kunisura is male.

このようにthisの参照先を固定させ、新しい関数として利用したい場合にbind()を利用します。

call()について

bind()と使い方は似ており、bindの場合は「新しく関数を作成する」ということでしたが、call()はそのまま実行時に呼び出します。

function gendar123(user){
  console.log(this.name + " is male.");
}

var userInfo = {
  name: "kunisura",
  gendar: gendar
};

// bindのケース
let gendar3 = gendar123.bind(userInfo);
gendar3(); // kunisura is male.

// callのケース
gendar123.call(userInfo); // kunisura is male.

callの場合は、第2引数に対して文字列を指定します。

function gendar456(name, age){
  console.log(this.name + " is male. And age is " + age);
}

var userInfo = {
  name: "kunisura",
  gendar: gendar
};

// bindのケース
let gendar4 = gendar456.bind(userInfo, userInfo.name, 25);
gendar4(); 
// kunisura is male. And age is 25

// callのケース
gendar456.call(userInfo, userInfo.name, 25); 
// kunisura is male. And age is 25

apply()について

apply()はcall()と基本的に同じですが、第二引数に文字列を指定することができず、「配列」で指定します。

function gendar456(name, age){
  console.log(this.name + " is male. And age is " + age);
}

var userInfo = {
  name: "kunisura",
  gendar: gendar
};

// bindのケース
let gendar4 = gendar456.bind(userInfo, userInfo.name, 25);
gendar4(); 
// kunisura is male. And age is 25

// callのケース
gendar456.call(userInfo, userInfo.name, 25); 
// kunisura is male. And age is 25

// applyのケース
gendar456.apply(userInfo, [userInfo.name, 25]);
// kunisura is male. And age is 25

さいごに

call()やapply()は使う時、結構好みに分かれることが多いですが、bind()は新しく関数を作成するという点でも多く使うことが多いと思われます。

callやapplyは主にクラスの継承という部分で実装するケースが想定されます。あとはデバッグ用とかですね。

よく理解して使うことがコード効率化の近道だと思いますので、是非参考にしてみてください。