使用Function.pr原型.apply()和Function.pr原型.call()调用函数有什么区别?
var func = function() {
alert('hello!');
};
函数.apply();vs func.call();
上述两种方法之间是否存在性能差异?何时最好使用呼叫转移应用,反之亦然?
使用Function.pr原型.apply()和Function.pr原型.call()调用函数有什么区别?
var func = function() {
alert('hello!');
};
函数.apply();vs func.call();
上述两种方法之间是否存在性能差异?何时最好使用呼叫转移应用,反之亦然?
当前回答
K.Scott Allen对这件事有很好的评论。
基本上,它们在处理函数参数的方式上有所不同。
apply()方法与call()方法相同,只是apply(需要一个数组作为第二个参数。数组表示目标方法的参数。"
So:
// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
其他回答
我想展示一个示例,其中使用了“valueForThis”参数:
Array.prototype.push = function(element) {
/*
Native code*, that uses 'this'
this.put(element);
*/
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9]
**详细信息:http://es5.github.io/#x15.4.4.7*
我只想在flatline的一篇解释得很好的文章中添加一个简单的例子,这让初学者很容易理解。
func.call(context, args1, args2 ); // pass arguments as "," separated value
func.apply(context, [args1, args2]); // pass arguments as "Array"
我们还使用“Call”和“Apply”方法更改引用,如下面的代码所定义
设Emp1={名称:'X',getEmpDetail:函数(年龄,部门){console.log(`Name:${this.Name}年龄:${Age}部门:${Department}`)}}Emp1.getEmpDetail(23,'交货')//改变“这个”的第一种方法设Emp2={名称:“Y”,getEmpDetail:Emp1.getEmpDetail}Emp2.getEmpDetail(55,“财务”)//使用“Call”和“Apply”更改“this”的第二种方法设Emp3={name:'Emp3_Object',}Emp1.getEmpDetail.call(Emp3,30,'管理员')//这里我们将ref从**Emp1更改为Emp3**对象//现在这将打印“Name=Emp3_Object”,因为它指向Emp3对象Emp1.getEmpDetail.apply(Emp3,[30,'管理员'])
要回答有关何时使用每个函数的问题,如果您不知道要传递的参数的数量,或者它们已经在数组或类似数组的对象中(例如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))。我还没有测试过它,所以可能会有差异,但它会非常特定于浏览器。如果数组中没有参数,则调用可能会更快,如果有,则应用可能会更快。
让我补充一点细节。
这两个调用几乎相等:
func.call(context, ...args); // pass an array as list with spread operator
func.apply(context, args); // is same as using apply
只有一个微小的区别:
排列运算符。。。允许传递可迭代参数作为要调用的列表。apply只接受类似数组的参数。
因此,这些呼叫是相辅相成的。在我们期望可迭代的地方,调用工作,在我们期望类似数组的地方,应用工作。
对于既可迭代又类似于数组的对象,比如真正的数组,我们技术上可以使用它们中的任何一个,但apply可能会更快,因为大多数JavaScript引擎内部对其进行了更好的优化。
这些to方法之间的区别在于,如何传递参数。
“A代表数组,C代表逗号”是一个方便的助记符。