有這麼一個題目:找出由數字組成的數組中最大值的索引。 (PS:不用考慮兼容性)
三個方案中,方案一最傳統最直接明了,相信也是大部分人腦海裡最早浮現出來的方案;方案二比方案一更簡潔,使用reduce方法替換了for循環;方案三最簡潔,沒有循環,沒有條件判斷,一行代碼解決問題。大部分人都喜歡追求代碼簡潔優雅,要是可選的話,相信很多人都會選擇方案三。
但問題來了,這三個方案中哪一個性能最好呢?
- 方案一:性能最差,因為它需要手動去遍歷數組,並且每個遍歷都需要進行條件判斷,所以這裡的性能損耗最大;
- 方案二:性能較好,因為它使用了JavaScript內置的reduce函數幫我們完成了方案一中手動完成的數組遍歷工作;JavaScript內置的方法肯定是比我們自己實現的要快,因此在同樣需要條件判斷的情況下,方案二肯定是由於方案一;
- 方案三:性能最好,因為相對方案二,它連條件判斷都省了,使用了Math.max替代。
但實際情況真的如上面所猜測的嗎?下面我們來做個測試:
測試地址:
indexOfMax-100,000 http://jsperf.com/indexofmax
indexOfMax-120,000 http://jsperf.com/indexofmax-120000
indexOfMax-130,000 http://jsperf.com/indexofmax-130000
測試結果如下:
從結果中可以看得出來,性能上:方案一最好,方案三次之,方案二最差;與上面猜測的結果完全相反。方案一最好猜測應該是浏覽器JavaScript解釋引擎對代碼進行了優化後執行的結果,優化後的代碼從底層實現上來看應該是比reduce、indexOf、Math.max等底層接口的性能更好,因此效率更高。
同時注意到,在Chrome下,當數組長度達到130,000時浏覽器拋出了最大調用堆棧的異常,我此前說過,浏覽器對調用堆棧的大小是有限制的。不同浏覽器對函數最大參數長度的限制是不一樣的,所以這裡需要注意下。
高級浏覽器的表現似乎比較統一,那麼IE的表現又怎麼樣呢?
IE下測試結果如下:
由於IE10、IE11越發往標准浏覽器靠攏,他們的表現跟IE9不同,倒與Chrome、Firefox有點類似,也是方案一最快,但是方案三最慢。這可能跟每個浏覽器自身的實現以及內部優化有關系。
So,做性能優化時的幾點建議:
- 內置的函數不一定是效率最好的,最簡潔優雅的寫法不一定可以帶來性能上的提升;
- JavaScript雖然是解釋型語言,但並不代表所做的操作越少性能越好;
- 要考慮不同平台以及浏覽器對接口的性能差異,按需權衡;
- 盡可能保持簡單的思考方式,不要過度設計,當發現性能問題時再嘗試去尋找解決方案;
- 性能優化需要數據支持,不能盲目相信經驗或者固有認知。