使用call
和apply
之间的区别是什么?调用函数?
varfunc=function(){
alert('hello!');
};
func.apply();
vsfunc.call();
两者之间是否存在性能差异上述两种方法?何时最好使用call
而不是apply
,反之亦然?
转载于:https://stackoverflow的.com/问题/1986896/什么-是最差之间呼叫和-适用?页=1&标签=票
不同之处在于apply
允许您使用arguments
调用该函数作为阵列;call
要求显式列出参数。一个有用的助记符是“Aarray和Ccomma。”
请参阅有关申请的MDN文档和致电。
伪语法:
theFunction.apply(valueForThis,arrayOfArgs)
theFunction。call(valueForThis,arg1,arg2,...)
从ES6开始,还有可能spread
数组,用于调用
函数,您可以在此处查看兼容性。
示例代码:
functiontheFunction(name,profession){
console.log(”我的名字是“+名字+”,我是“+专业+”。“;;
}TheFunction(”John“,”fireman“);
theFunction.apply(undefined,[”Susan“,”schoolteacher“]);
theFunction.call(未定义,“克劳德”,“数学家”);
theFunction.call(undefined,...[“Matthew”,“物理学家”]);//与扩展运算符一起使用
K.ScottAllen已关于此事的一个很好的写作。
基本上,它们在处理函数参数方面有所不同。
apply()方法与call()相同,但apply()需要一个数组作为第二个参数。数组表示目标方法的参数。“
所以:
//假设你有f
函数f(消息){...}
f.call(接收者,“测试”);
f.apply(接收者,[“测试”]);
要回答有关何时使用每个功能的部分,如果您不知道该号码,请使用apply
您将要传递的参数,或者它们是否已经在数组或类似数组的对象中(如arguments
对象来转发您自己的参数。否则,请使用call
,因为没有必要将参数包装在数组中。
f.call(thisObject,a,b,c);//固定数量的参数
ff。(thisObject,arguments);//转发此函数的参数
varargs=[];
while(...){
\args.push(some_value());
}
nf.apply(thisObject,args);//未知数量的参数
当我没有传递任何参数时(比如你的例子),我更喜欢call
因为我调用函数。apply
意味着你将函数应用于(不存在的)参数。
除非您愿意,否则不应存在任何性能差异使用apply
并将参数包装在一个数组中(例如f.apply(thisObject,[a,b,c])
而不是f.call(thisObject,a,b,c)
)。我没有对它进行过测试,因此可能存在差异,但它会特定于浏览器。如果你没有数组中的参数,那么call
可能会更快,如果你这样做,apply
会更快。
虽然这是一个古老的话题,但我只想指出.call比.apply略快。我无法确切地告诉你原因。
参见jsPerf,http://jsperf.com/test-call-vs-apply/3
[更新]
DouglasCrockford简要提到了两者之间的区别,这可能有助于解释性能差异......http://youtu.be/ya4UHuXNygM?t=15m52s
Apply接受一系列参数,而Call接受零个或多个个体参数!啊哈!
.apply(this,[...])
.call(this,param1,param2,param3,param4...)
我想展示一个例子,其中使用'valueForThis'参数:
Array.prototype.push=function(element){
/*
本机代码*,使用'this'
this.put(element);
*/
}
vararray=[];
array.push(1);
array.push.apply(数组,[2,3]);
Array.prototype.push.apply(数组,[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*
这是一个很好的助记符。Apply使用Arrays而Always需要一个或两个参数。当你使用C时,你必须C计算参数的数量。
我们可以区分调用和应用方法,如下所示
CALL:带参数的函数单独提供。 如果你知道要传递的参数或者没有传递参数,你可以使用call。
APPLY:调用一个带有作为数组提供的参数的函数。如果您不知道将有多少参数传递给函数,则可以使用apply。
使用applyovercall有一个优点,我们不需要更改参数个数我们只能更改传递的数组。
性能没有太大差别。但我们可以说,与apply相比,调用有点快,因为数组需要在apply方法中进行求值。
这是一篇小帖子,我写到:
http://sizeableidea.com/call-versus-apply-javascript/
varobj1={which:“obj1”},
obj2={which:“obj2”};
functionexecute(arg1,arg2){
console.log(this.which,arg1,arg2);
}
//使用call
execute.call(obj1,“dan”,“stanhope”);
//输出:obj1danstanhope
//使用apply
execute.apply(obj2,[“dan”,“stanhope”]);
//输出:obj2danstanhope
//使用旧学校
execute(“dan”,“stanhope”);
//output:undefined“dan”“stanhope”
Call()采用逗号分隔的参数,例如:
.call(scope,arg1,arg2,arg3)
和apply()接受一个参数数组,例如:
。apply(scope,[arg1,arg2,arg3])
这里有几个用法示例: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/
有时一个对象借用另一个对象的函数很有用,这意味着借用对象只是简单地执行lent函数,就像这是它自己的。
一个小代码示例:
varfriend={
car:false,
lendCar:function(canLend){
this.car=canLend;
}
};
我={
汽车:false,
gotCar:function(){
返回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
达成同样的效果,我认为还有至少一个你不能使用call
的地方,但只能使用apply
。那是你想要支持继承并想要调用构造函数的时候。
这个函数允许你创建类,它们也支持通过扩展其他类来创建类。
functionmakeClass(properties){
varctor=properties['constructor']||function(){}
varSuper=properties['extends'];
varClass=function(){
//这里'call'不起作用,只有'apply'可以!!!
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];
});
返回Class;
}
//用法
varCar=makeClass({
构造函数:函数(名称){
this.name=name;
},
yourName:function(){
返回此.name;
}
});
//我们现在有一个Car类
varcarInstance=newCar('Fiat');
nInInstance.youName();//ReturnsFiat
varSuperCar=makeClass({
constructor:function(ignore,power){
this.power=power;
},
extends:Car,
yourPower:function(){
returnthis.power;
}
});
//我们现在有一个SuperCar类,它是Car
var的子类superCar=newSuperCar('BMWxy',2.6);
superCar.yourName();//返回BMWxy
superCar.yourPower();//返回2.6
使用Call,Apply和Bind的另一个例子。 Call和Apply之间的区别很明显,但Bind是这样的:
}
functionPerson(name){
this.name=name;
}
Person.prototype.getName=function(a,b){
returnthis.name+“”+a+“”+b;
}
varreader=newPerson('JohnSmith');
reader.getName=function(){
//Apply和Call执行函数并返回值
//也注意提取'getName'原型的不同方法
varbaseName=Object.getPrototypeOf(this).getName.apply(this,[“isa”,“boy”]);
console.log(“Apply:”+baseName);
varbaseName=Object.getPrototypeOf(reader).getName.call(this,“isa”,“boy”);
console.log(“Call:”+baseName);
//绑定返回可以调用的函数
varbaseName=Person.prototype.getName.bind(this,“isa”,“boy”);
console.log(“Bind:”+baseName());
}
reader.getName();
/*输出
应用:JohnSmith是个男孩
呼叫:JohnSmith是男孩
Bind:JohnSmith是个男孩
*/
这些方法之间的区别在于,您希望如何传递参数。
“Aforarray和Cforcomma“是一个方便的助记符。
调用和应用两者用于在执行函数时强制this
值。唯一的区别是call
需要n+1
参数,其中1是this
和'n'arguments
。apply
只接受两个参数,一个是this
,另一个是参数数组。
我在applyover
call
是我们可以轻松地将函数调用委托给其他函数;
functionsayHello(){
console.log(this,arguments);
}
函数hello(){
sayHello.apply(this,arguments);
}
varobj={name:'myname'}
hello。call(obj,'some','arguments');
观察我们如何轻松地将hello
委托给sayHello代码>使用
apply
,但是使用call
,这很难实现。
区别在于call()
分别获取函数参数,apply()
获取数组中的函数参数。
主要区别在于,使用call,我们可以正常更改范围并传递参数,但apply允许您使用参数调用它一个数组(将它们作为数组传递)。但就你在代码中的作用而言,它们非常相似。
虽然这个函数的语法几乎与 apply()的语法相同,最根本的区别是call()接受一个参数 list,而apply()接受一个参数数组。
如你所见,那里并不是一个很大的区别,但仍有一些情况我们更喜欢使用call()或apply()。例如,查看下面的代码,它使用apply方法从MDN中查找数组中的最小和最大数字:
//数组中的最小/最大数字
varnumbers=[5,6,2,3,7];
//使用Math.min/Math.maxapply
varmax=Math.max.apply(null,numbers);
//这大约等于Math.max(数字[0],...)
//或Math.max(5,6,...)
varmin=Math.min.apply(null,数字)
所以主要区别在于我们传递参数的方式:
调用:
function.call(thisArg,arg1,arg2,...);
应用
function.apply(thisArg,[argsArray]);