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

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

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

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


当前回答

虽然这是一个老话题,但我只是想指出,.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…)

其他回答

虽然这是一个老话题,但我只是想指出,.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…)

要回答有关何时使用每个函数的问题,如果您不知道要传递的参数的数量,或者它们已经在数组或类似数组的对象中(例如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()都是位于Function.prototype上的方法。因此,它们可以通过原型链在每个函数对象上使用。call()和apply()都可以执行具有指定值this的函数。

call()和apply()之间的主要区别是必须向其中传递参数的方式。在call()与apply(()中,您都将希望作为值的对象作为第一个参数传递为this。其他参数的不同之处如下:

使用call(),您必须正常输入参数(从第二个参数开始)使用apply(),必须传入参数数组。

例子:

让obj={val1:5,值2:10}常量总和=函数(val3,val4){返回this.val1+this.val2+val3+val4;}console.log(summary.apply(obj,[2,3]));//首先,我们在第一个参数中为其赋值//使用apply,我们必须传入一个数组console.log(summary.call(obj,2,3));//通过调用,我们可以单独传入每个参数

为什么我需要使用这些功能?

在javascript中,这个值有时很棘手。该值在执行函数时确定,而不是在定义函数时确定。如果我们的函数依赖于此绑定的权限,我们可以使用call()和apply()来强制执行此行为。例如:

var name='unwantedGlobalName';常量对象={name:“Willem”,sayName(){console.log(this.name);}}let copiedMethod=obj.sayName;//我们将函数存储在copiedmethod变量中copiedMethod();//现在是窗口,unwantedGlobalName将被记录copiedMethod.call(obj);//我们强制这是obj,Willem被记录

这些to方法之间的区别在于,如何传递参数。

“A代表数组,C代表逗号”是一个方便的助记符。

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

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

伪语法:

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

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

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

示例代码:

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