使用Function.pr原型.apply()和Function.pr原型.call()调用函数有什么区别?

var func = function() {
  alert('hello!');
};

函数.apply();vs func.call();

上述两种方法之间是否存在性能差异?何时最好使用呼叫转移应用,反之亦然?


当前回答

有时,一个对象借用另一个对象的函数是有用的,这意味着借用对象只需像执行自己的函数一样执行借出函数。

一个小代码示例:

var friend = {
    car: false,
    lendCar: function ( canLend ){
      this.car = canLend;
 }

}; 

var me = {
    car: false,
    gotCar: function(){
      return this.car === true;
  }
};

console.log(me.gotCar()); // false

friend.lendCar.call(me, true); 

console.log(me.gotCar()); // true

friend.lendCar.apply(me, [false]);

console.log(me.gotCar()); // false

这些方法对于为对象提供临时功能非常有用。

其他回答

K.Scott Allen对这件事有很好的评论。

基本上,它们在处理函数参数的方式上有所不同。

apply()方法与call()方法相同,只是apply(需要一个数组作为第二个参数。数组表示目标方法的参数。"

So:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);

区别在于apply允许您以数组的形式调用带有参数的函数;调用要求显式列出参数。一个有用的助记符是“A代表数组,C代表逗号。”

请参阅MDN的申请和通话文档。

伪语法:

函数.应用(值For This,arrayOfArgs)

函数调用(此值,arg1,arg2,…)

从ES6开始,还可以扩展数组以与调用函数一起使用,您可以在这里看到兼容性。

示例代码:

函数函数(名称、专业){console.log(“我的名字是”+name+“,我是”+profession+“。”);}函数(“John”,“fireman”);函数.应用(未定义,[“Susan”,“学校老师”]);函数调用(未定义,“克劳德”,“数学家”);函数调用(未定义,…[“Matthew”,“物理学家”]);//与排列运算符一起使用

有时,一个对象借用另一个对象的函数是有用的,这意味着借用对象只需像执行自己的函数一样执行借出函数。

一个小代码示例:

var friend = {
    car: false,
    lendCar: function ( canLend ){
      this.car = canLend;
 }

}; 

var me = {
    car: false,
    gotCar: function(){
      return this.car === true;
  }
};

console.log(me.gotCar()); // false

friend.lendCar.call(me, true); 

console.log(me.gotCar()); // true

friend.lendCar.apply(me, [false]);

console.log(me.gotCar()); // false

这些方法对于为对象提供临时功能非常有用。

要回答有关何时使用每个函数的问题,如果您不知道要传递的参数的数量,或者它们已经在数组或类似数组的对象中(例如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

当我不传递任何参数时(如您的示例),我更喜欢调用,因为我在调用函数。apply将暗示您正在将函数应用于(不存在的)参数。

应该不会有任何性能差异,除非您使用apply并将参数包装在数组中(例如f.apply(thisObject,[a,b,c])而不是f.call(thisObject,a,b,c))。我还没有测试过它,所以可能会有差异,但它会非常特定于浏览器。如果数组中没有参数,则调用可能会更快,如果有,则应用可能会更快。

虽然这是一个老话题,但我只是想指出,.call比.apply稍快。我不能告诉你确切的原因。

参见jsPerf,http://jsperf.com/test-call-vs-apply/3


[更新!]

Douglas Crockford简要提到了两者之间的差异,这可能有助于解释性能差异。。。http://youtu.be/ya4UHuXNygM?t=15m52s

Apply接受一个参数数组,而Call接受零个或多个单独的参数!啊哈!

.apply(此,[…])

.调用(this,param1,param2,param3,param4…)