繁体   English   中英

为什么打电话比申请快得多?

[英]Why is call so much faster than apply?

我想知道是否有人知道为什么 callapply快得多? 在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月)

15.3.4.3 Function.prototype.apply(thisArg,argArray)

在带有参数thisArg和argArray的对象func上调用apply方法时,将执行以下步骤:

  1. 如果IsCallable(func)false ,则抛出TypeError异常。

  2. 如果argArraynullundefined ,则return调用func[[Call]]内部方法的结果,将thisArg作为this值和空参数列表提供。

  3. 如果Type(argArray)不是Object ,则抛出TypeError异常。
  4. len是使用参数"length"调用argArray[[Get]]内部方法的argArray
  5. nToUint32(len)
  6. argList为空List
  7. index为0。
  8. index < n重复
  9. indexNameToString(index)
  10. nextArg是调用nextArg[[Get]]内部方法的argArray其中indexName作为参数。
  11. 附加nextArg作为最后一个元素argList
  12. index设置为index + 1
  13. 返回调用func[[Call]]内部方法的结果,提供thisArg作为this值,并将argList作为参数列表。

15.3.4.4 Function.prototype.call(thisArg [,arg1 [,arg2,...]])

在带有参数thisArg和可选参数arg1,arg2等的对象func上call方法时,将执行以下步骤:

  1. 如果IsCallable(func)false ,则抛出TypeError异常。
  2. argList为空List
  3. 如果使用多个参数调用此方法, argList arg1开始以从左到右的顺序将每个参数附加为argList的最后一个元素
  4. 返回调用func[[Call]]内部方法的结果,提供thisArg作为this值,并将argList作为参数列表。

正如我们所看到的,指定apply的格式显然更重,并且由于需要更改参数的格式以及最终需要它们的方式,因此需要做更多的工作。
还有在一些测试, apply其不在需要call由于输入格式的差别。

另一个关键点是参数循环的方式(在apply步骤4-12,隐含在call第3步中):循环的整个设置在apply执行,而不管实际上有多少参数,在call只有在需要时才能完成所有这些工作。
另外值得注意的是,没有指定call步骤3的方式,这有助于解释不同浏览器行为的巨大差异。

所以简要回顾一下: callapply更快,因为输入参数已经根据内部方法的需要进行了格式化。

请务必阅读以下评论以进一步讨论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM