[英]Why is call so much faster than apply?
我想知道是否有人知道为什么 call
比apply
快得多? 在chrome中,它大约快4倍,在firefox中大约30倍,我甚至可以制作一个自定义原型, apply2
,它(在大多数情况下)运行速度和apply
速度一样快(从角度来看的想法):
Function.prototype.apply2 = function( self, arguments ){
switch( arguments.length ){
case 1: this.call( self, arguments[0] ); break;
case 2: this.call( self, arguments[0], arguments[1] ); break;
case 3: this.call( self, arguments[0], arguments[1], arguments[2] ); break;
case 4: this.call( self, arguments[0], arguments[1], arguments[2], arguments[3] ); break;
case 5: this.call( self, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4] ); break;
case 6: this.call( self, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5] ); break;
case 7: this.call( self, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6] ); break;
case 8: this.call( self, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7] ); break;
case 9: this.call( self, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8] ); break;
case 10: this.call( self, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9] ); break;
default: this.apply( self, arguments ); break;
}
};
那么有谁知道为什么?
参考ECMAScript语言规范5.1版(2011年6月) :
在带有参数thisArg和argArray的对象func上调用apply
方法时,将执行以下步骤:
如果IsCallable(func)
为false
,则抛出TypeError
异常。
如果argArray
为null
或undefined
,则return
调用func
的[[Call]]
内部方法的结果,将thisArg
作为this
值和空参数列表提供。
Type(argArray)
不是Object
,则抛出TypeError
异常。 len
是使用参数"length"
调用argArray
的[[Get]]
内部方法的argArray
。 n
为ToUint32(len)
。 argList
为空List
。 index
为0。 index < n
重复 indexName
为ToString(index)
。 nextArg
是调用nextArg
的[[Get]]
内部方法的argArray
其中indexName
作为参数。 nextArg
作为最后一个元素argList
。 index
设置为index + 1
。 func
的[[Call]]
内部方法的结果,提供thisArg
作为this
值,并将argList
作为参数列表。 在带有参数thisArg和可选参数arg1,arg2等的对象func上call
方法时,将执行以下步骤:
IsCallable(func)
为false
,则抛出TypeError
异常。 argList
为空List
。 argList
arg1
开始以从左到右的顺序将每个参数附加为argList
的最后一个元素 func
的[[Call]]
内部方法的结果,提供thisArg
作为this
值,并将argList
作为参数列表。 正如我们所看到的,指定apply
的格式显然更重,并且由于需要更改参数的格式以及最终需要它们的方式,因此需要做更多的工作。
还有在一些测试, apply
其不在需要call
由于输入格式的差别。
另一个关键点是参数循环的方式(在apply
步骤4-12,隐含在call
第3步中):循环的整个设置在apply
执行,而不管实际上有多少参数,在call
只有在需要时才能完成所有这些工作。
另外值得注意的是,没有指定call
步骤3的方式,这有助于解释不同浏览器行为的巨大差异。
所以简要回顾一下: call
比apply
更快,因为输入参数已经根据内部方法的需要进行了格式化。
请务必阅读以下评论以进一步讨论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.