basyura's blog

あしたになったらほんきだす。

javascript の apply と call

apply メソッドは 2 つの引数、 thisArg および argArray をとり、オブジェクトの Call プロパティを使用して、関数呼出しを実行する。オブジェクトが Call プロパティを持っていない場合、例外 TypeError が投げられる。
thisArg が null または undefined の場合、呼出された関数は this 値としてグローバルオブジェクトを渡される。そうでなければ、呼出された関数は this 値として ToObject(thisArg) を渡される。
argArray が null または undefined の場合、呼出された関数は引数を渡されない。そうでなければ、 argArray が配列でも arguments オブジェクト (10.1.8 参照) でもない場合、例外 TypeError が投げられる。 argArrayが 配列または arugments オブジェクトのいずれかである場合、関数は (ToUint32(argArray.length)) 個の引数argArray[0], argArray[1], ... argArray[ToUint32(argArray.length)-1] を渡される。
apply メソッドの length プロパティは 2 である。

15.3.4.3 Function.prototype.apply (thisArg, argArray)

call メソッドは 1 つ以上の引数を取り、thisArg および(選択的に) arg1, arg2, ... をとり、オブジェクトのCall プロパティを使用して、関数呼び出しを実行する。オブジェクトが Call プロパティを持っていない場合、TypeError 例外が投げられる。呼出された関数は、引数として arg1、arg2 などを渡される。 thisArg が null または undefined の場合、呼出された関数は this 値としてグローバルオブジェクトを渡される。そうでなければ、呼出された関数は this 値として ToObject(thisArg) を渡される。 call メソッドの length プロパティは 1 である。

[http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/15-3_Function_Objects.html#section-15.3.4.3:title=15.3.4.4 Function.prototype.call (thisArg [ , arg1 [ , arg2, … ] ] )]

違いは引数が配列かそうでないかの様に思えるのだけど、実行速度が call の方が早いとか。
試してみる。

var max = 100000;
var list = [1,2,3,4,5,6,7,8,9,10];

var start = Date.now();
for (var i = 0 ; i < max ; i++) {
  Array.prototype.slice.apply(list , [1]);
}
print(Date.now() - start); //=> 410

start = Date.now();
for (var i = 0 ; i < max ; i++) {
  Array.prototype.slice.call(list , 1);
}
print(Date.now() - start); //=> 226

call の方が 2 倍近く早い。といっても一回当たりの差は誤差に近い気がするけど。
速さの違いは単純に処理(判定)の数なのかなぁ。