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

时间:2014-05-20 20:42:40

标签: javascript

我想知道是否有人知道为什么 callapply快得多?在chrome中,它大约快4倍,在firefox中大约是30倍,我甚至可以制作一个自定义原型apply2,它(在大多数情况下)运行速度是apply的2倍(从角度来看的想法:

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;
    }   
};

所以有人知道为什么吗?

1 个答案:

答案 0 :(得分:15)

引用ECMAScript Language Specification 5.1 Edition (June 2011)

15.3.4.3 Function.prototype.apply(thisArg,argArray)

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

  1. 如果IsCallable(func)false,则抛出TypeError例外。

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

    < / LI>
  3. 如果Type(argArray)不是Object,则抛出TypeError例外。
  4. len成为调用[[Get]]内部方法的结果 带有参数argArray的{​​{1}}。
  5. "length"成为n
  6. ToUint32(len)为空argList
  7. List为0。
  8. index
  9. 时重复
  10. index < n成为indexName
  11. ToString(index)成为调用nextArg内部方法的结果  以[[Get]]为参数的argArray
  12. indexName添加为nextArg的最后一个元素。
  13. argList设为index
  14. 返回调用index + 1 [[Call]]内部方法的结果,  提供func作为thisArg值,this作为列表      参数。
  15. 15.3.4.4 Function.prototype.call(thisArg [,arg1 [,arg2,...]])

    当使用参数thisArg和可选参数arg1,arg2等在对象func上调用argList方法时,将执行以下步骤:

    1. 如果callIsCallable(func),则抛出false例外。
    2. TypeError为空argList
    3. 如果使用多个参数调用此方法,则在左侧 以List开头的正确顺序将每个参数作为最后一个附加 arg1
    4. 的元素
    5. 返回调用argList [[Call]]内部方法的结果, 提供func作为thisArg值,this作为列表 参数。

    6. 正如我们所看到的,指定argList的格式显然更重,并且由于需要更改参数的格式以及最终需要它们的方式,因此需要执行更多操作。
      apply中有许多检查由于输入格式的不同而在apply中不是必需的。

      另一个关键点是参数循环的方式(call中的步骤4-12,隐含在apply的第3步中):循环的整个设置在{ {1}}无论实际存在多少个参数,call所有这些只在需要时才会完成 此外,值得注意的是,apply中实施步骤3的方式未被指定,这有助于解释不同浏览器行为的巨大差异。

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

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