関数を呼び出すのにcall
とapply
の違いは何ですか?
var func = function() {
alert('hello!');
};
func.apply();vs
func.call();` です。
前述の 2 つのメソッドにはパフォーマンスの違いがありますか?どのような場合に apply
よりも call
を使用するのがベストで、その逆もまた然りですか?
違いは、apply
では `arguments
を配列にして関数を呼び出すことができ、call
ではパラメータを明示的に列挙する必要があることです。便利なニーモニックは、_"Aはarray、Cはcomma."_です。
MDN'の[apply][1]とcallのドキュメントを参照してください。
擬似的な構文です。
theFunction.apply(valueForThis, arrayOfArgs)
です。
theFunction.call(valueForThis, arg1, arg2, ...)
また、ES6では、call
関数で使用するために配列をspread
することも可能で、その互換性はこちらで確認できます。
サンプルコードです。
function theFunction(name, profession) {
console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator
[1]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply
K.Scott Allenがこの件についてa nice writeupを書いています。
基本的には、関数の引数をどのように扱うかという点で違いがあります。
apply()メソッドはcall()と同じですが、 apply()は2番目のパラメータとして配列を必要とします。この配列は、対象となるメソッドの引数を表します。
というわけです。
// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
各関数をいつ使用するかという部分についてお答えしますと、渡す引数の数がわからない場合や、引数がすでに配列や配列のようなオブジェクト(自分の引数を転送するためのarguments
オブジェクトのようなもの)に入っている場合には、apply
を使用します。それ以外の場合は、引数を配列で包む必要がないので、call
を使います。
f.call(thisObject, a, b, c); // Fixed number of arguments
f.apply(thisObject, arguments); // Forward this function's arguments
var args = [];
while (...) {
args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments
引数を渡さない場合(あなたの例のように)、私はcall
を好みます。なぜなら私は関数を呼び出しているからです。apply`は、(存在しない)引数に関数を適用していることを意味します。
性能的な違いはないと思いますが、apply
を使って引数を配列で囲む場合は別です(例:f.call(thisObject, a, b, c)
の代わりにf.apply(thisObject, [a, b, c])
)。テストはしていないので、違いがあるかもしれませんが、非常にブラウザに依存するでしょう。まだ引数が配列になっていない場合は call
の方が速く、配列になっている場合は apply
の方が速いと思われます。