Pocket

applyメソッドの動作

まずはapplyメソッドの基本動作から。baz()関数を作成して、関数内でthisを参照してみます。

consoleで確認すると、applyメソッドの引数で渡したオブジェクトがthisの参照元になっているのがわかります。(applyメソッドがないとundefinedが返ってきます。当たり前ですけど。)
thisの値をオブジェクトobjにバインドしてると言ったほうがわかりやすいかも。

渡すオブジェクトの中に関数を定義して、その関数を呼び出してみます。

結果は、method call.obj foo valueとコンソールに出力されているので、thisの参照先はobjであると言えます。つまりはapplyメソッドの第一引数に渡すオブジェクトにthisの値をバインドするので、別のオブジェクトを渡すことでそのオブジェクトにオブジェクトobjと同じ振る舞いをさせることができます。

結果は、method call.obj2 foo valueとobj2で定義した値が表示されたので、thisの参照先がobj2であると言えます。オブジェクトobjがレシーバの役目になっている(レシーバオブジェクト)ことがわかります。とても便利。

callメソッドの動作

次にcallメソッドですが、applyメソッドとほぼ同じ動作をします。試しに、先程のプログラムのapplyメソッドをcallメソッドに書き換えて実行してみます。

結果は、method call.obj2 foo valueと表示されました。applyメソッドと同じ動作をしたということになります。あれ?じゃあcallメソッドってapplyメソッドとどこが違うの?という話になりますので、続いて2つのメソッドに違いについて。

applyメソッドとcallメソッドの違い

それでは2つのメソッドの違いを見ていきます。

引数の違い

applyメソッドとcallメソッドの第一引数にオブジェクトを渡す点は共通ですが、第二引数以降の引数の渡し方が異なります。applyメソッドは配列でまとめて渡すパターン、callメソッドはカンマ区切りで渡すパターンになります。以下、実行例。

結果もそれぞれapply a apply b obj foo valuecall a call b obj foo valueと出力されます。

コンストラクタの連鎖

継承のようなことができるという認識なのだがあっているのか?という自問自答。FooFunc()クラスのコンストラクタ(a,b)を、BarFunc()とBazFunc()のコンストラクタでコールします。これがapplyメソッドではできない。

結果は、以下の通り返ってきます。BarFunc()とBazFunc()はそれぞれ独自で設定した値(cとdの値)が設定されています。

無名関数を呼び出す

オブジェクトに関数を定義する際にループのインデックス値を保持させたい場合、無名関数の中で関数オブジェクト(クロージャー)を生成することで、その中で保持させることができます。これもapplyメソッドではできないこと。

変数iの値を保持したまま関数を呼び出すことができました。\(^o^)/

参考サイト

MDN: Function.prototype.apply()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
MDN: Function.prototype.call()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/call