使用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();
上述两种方法之间是否存在性能差异?何时最好使用呼叫转移应用,反之亦然?
当前回答
这些to方法之间的区别在于,如何传递参数。
“A代表数组,C代表逗号”是一个方便的助记符。
其他回答
K.Scott Allen对这件事有很好的评论。
基本上,它们在处理函数参数的方式上有所不同。
apply()方法与call()方法相同,只是apply(需要一个数组作为第二个参数。数组表示目标方法的参数。"
So:
// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
让我补充一点细节。
这两个调用几乎相等:
func.call(context, ...args); // pass an array as list with spread operator
func.apply(context, args); // is same as using apply
只有一个微小的区别:
排列运算符。。。允许传递可迭代参数作为要调用的列表。apply只接受类似数组的参数。
因此,这些呼叫是相辅相成的。在我们期望可迭代的地方,调用工作,在我们期望类似数组的地方,应用工作。
对于既可迭代又类似于数组的对象,比如真正的数组,我们技术上可以使用它们中的任何一个,但apply可能会更快,因为大多数JavaScript引擎内部对其进行了更好的优化。
有时,一个对象借用另一个对象的函数是有用的,这意味着借用对象只需像执行自己的函数一样执行借出函数。
一个小代码示例:
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
这些方法对于为对象提供临时功能非常有用。
尽管call和apply实现了相同的功能,但我认为至少有一个地方不能使用call,只能使用apply。这是您希望支持继承并希望调用构造函数的时候。
这里有一个函数允许您创建类,它也支持通过扩展其他类来创建类。
function makeClass( properties ) {
var ctor = properties['constructor'] || function(){}
var Super = properties['extends'];
var Class = function () {
// Here 'call' cannot work, only 'apply' can!!!
if(Super)
Super.apply(this,arguments);
ctor.apply(this,arguments);
}
if(Super){
Class.prototype = Object.create( Super.prototype );
Class.prototype.constructor = Class;
}
Object.keys(properties).forEach( function(prop) {
if(prop!=='constructor' && prop!=='extends')
Class.prototype[prop] = properties[prop];
});
return Class;
}
//Usage
var Car = makeClass({
constructor: function(name){
this.name=name;
},
yourName: function() {
return this.name;
}
});
//We have a Car class now
var carInstance=new Car('Fiat');
carInstance.youName();// ReturnsFiat
var SuperCar = makeClass({
constructor: function(ignore,power){
this.power=power;
},
extends:Car,
yourPower: function() {
return this.power;
}
});
//We have a SuperCar class now, which is subclass of Car
var superCar=new SuperCar('BMW xy',2.6);
superCar.yourName();//Returns BMW xy
superCar.yourPower();// Returns 2.6
从Function.pr原型.apply()上的MDN文档中:
apply()方法调用具有给定this值的函数作为数组(或类似数组的对象)提供的参数。语法fun.apply(thisArg,[argsArray])
从Function.pr原型.call()上的MDN文档中:
call()方法调用具有给定this值和单独提供的参数的函数。语法fun.call(thisArg[,arg1[,arg2[,…]]])
从JavaScript中的Function.apply和Function.call:
apply()方法与call()方法相同,只是apply(需要数组作为第二参数。数组表示的参数目标方法。
代码示例:
var doSomething=函数(){var arr=[];for(参数中的i){if(this〔arguments〔i〕〕的类型!==“undefined”){arr.push(this〔arguments〔i〕〕);}}返回arr;}var输出=函数(位置,对象){document.body.innerHTML+=“<h3>输出”+位置+“</h3>”+JSON.stringify(obj)+“\n<br>\n<br><hr>”;}输出(1,doSomething(“一”,“二”,“二”,“一”));输出(2,doSomething.apply({一:‘Steven’,二:‘Jane’}[“一”,“二”,“二”,“一”]));输出(3,doSomething.call({一:‘Steven’,二:‘Jane’},“一”,“二”,“二”,“一”));
另请参见此Fiddle。