こんにちは、ともです。
この記事ではJavaScriptのFunctionオブジェクトが提供するメンバーであるcallとapplyというメソッドについて僕の理解をまとめて行きます。
参考にしたものは下記です。
call/applyメソッドとは
call/applyメソッドを利用することで、オブジェクトに登録されたメソッドを実行することができます。
function hoge() {
console.log('do hoge');
}
hoge();// do hoge
hoge.call();// do hoge
hoge.apply();// do hoge
単純にhoge();
で実行しても、call();
で実行しても、apply();
で実行してもhogeメソッドを実行していることが分かります。
ここで1つの疑問が浮かびました。
なぜ、call/applyでメソッドを実行するのか理解するためにはthisの振る舞いについて理解する必要があります。
thisの参照先に関する理解は下記の記事にまとめました。
thisの参照先はthisが記載された場所やstrictモードの違いによって変わります。
function hoge() {
console.log(this);
}
hoge();// window
hoge.call();// window
hoge.apply();// window
グローバルコンテキストに記述されたメソッド内のthisキーワードの参照先はstrictモードでundefined、非strictモードでwindowです。
上記例ではhogeメソッド内のthisは非strictモードなのでwindowを参照することになります。
ではthisキーワードを参照先をwindowオブジェクトでは無く、別のオブジェクトに変更してhogeメソッドを実行するにはどのすれば良いのでしょうか。
そこでcall/applyメソッドが登場します。
call/applyを利用してみる
var data = 'Global data';
var obj1 = {
data: 'obj1 data'
};
function hoge() {
console.log(this.data);
}
hoge(); // Global data
hoge.call(obj1);// obj1 data
hoge.apply(obj1);// obj1 data
call/applyの第一引数にthisで参照して欲しいオブジェクトをしてしました。
hoge();
の場合はthisの参照先のルールに基づきwindowhoge.call(obj1);
の場合は参照先にobj1を指定しているためobj1hoge.apply(obj1);
の場合は参照先にobj1を指定しているためobj1
では、call/applyの違いは何なのでしょうか?
call/applyの違い
利用方法は下記となっています。
func.call(thisArg, arg1, arg2, ...)
func.apply(thisArg, [argsArray])
引数のリストをみると、
- callはメソッド実行時の引数を1つ1つセットして実行
- applyはメソッド実行時の引数を配列にまとめて実行
この違いだけです。
var name = 'Tokyo'
var pref = {
name: 'Osaka'
}
function showName(family, name) {
console.log(family + name + 'from:' + this.name);
}
showName('田中', '太郎'); // 田中太郎 from Tokyo
showName.call(pref, '田中', '太郎'); // 田中太郎 from Osaka
showName.apply(pref, ['田中', '太郎']); // 田中太郎 from Osaka
上記のように、callは1つ1つ、applyは配列として引数を渡しました。
thisの参照先もprefに変更できていることが分かります。
まとめ
call/applyについて理解をまとめました。
メソッド内のthisの参照先を変更するためにcall/applyを利用することが分かりました。
また、call/applyの違いは引数の与え方の違いだけでした。