[英]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.