[翻譯]你應該避免的3個Javascript性能錯誤
- 2019 年 12 月 22 日
- 筆記
如果我告訴你,你知道的一切都是假的,如果你學的一些近幾年發佈的深受喜愛的 ECMAScript 的主要特性,是很容易導致性能問題的,會發生什麼。
故事發生在幾年前,讓我們回到 ES5 的天真時代…
我深深地記得 ES5 發佈的那天,我們喜愛的 Javascript 引入了一些優秀的數組方法,它們是 forEach, reduce, map, filter——這些方法讓我們感受到語言不斷發展,功能越來越強大,寫代碼變得更有趣和流暢,代碼變得更通俗易懂。
幾乎同時,誕生了 Node.js ,它使得我們能平穩地從前端過渡到後端,同時真正重新定義了全棧開發。
現在,Node.js ,在 V8 引擎上使用最新的 ECMAScript ,爭取被認為是主流的服務端開發語言之一。因此,它需要證明在性能方面是高效的。當然,有很多性能參數需要考慮,沒有某種語言的性能可以所有參數都優於其他語言。但是,用開箱即用的方法如上面提到的函數寫 javascript 對你的應用性能的影響到底是有利還是有害呢?
此外 ,javascript不僅僅是為了展示視圖而被認為是客戶端開發的合理方案,因為用戶的電腦性能會變得更好,網絡會更快,但是當我們需要一個超高性能的應用或者非常複雜的應用時,我們能依賴用戶的電腦嗎?
為了測試這些問題,我嘗試比較幾個場景並深入理解我的實驗結果,我在 Node.js v10.11.0、Chrome瀏覽器、macOS上做的測試。
1.遍曆數組
我做的第一個場景是對一個 10萬條數據的數組求和。這是現實中一個有效的方法,我從數據庫中獲取了一個列表並求和,沒有額外的 DB 操作。
我用 for , for-of, while, forEach, reduce 比較了在隨機的 10萬條數據中求和,結果如下:
For Loop, average loop time: ~10 microseconds For-Of, average loop time: ~110 microseconds ForEach, average loop time: ~77 microseconds While, average loop time: ~11 microseconds Reduce, average loop time: ~113 microseconds
從 google 上查如何做數組求和時,reduce 是推薦的最好的實現方式,但是卻是性能最差的。我的必用方法 forEach 性能也不是很好。即使是最新的 ES6 方法 for-of ,只是提供了最差的性能方法。它比舊的 for 循環方法(也是性能最好的方法)差了 10 倍。
最新的和最推薦的方法怎麼可以使得 Javascript 變得如此慢,造成這個的原因主要有 2 個。reduce 和 forEach 需要一個執行一個回調函數,這個函數被遞歸調用並使堆棧"膨脹",以及對執行代碼進行附加操作和驗證。
2.複製數組
複製數組看起來不是一個有趣的場景,但這是不可變函數的基石,它在生成輸出時不會修改輸入。
性能測試同樣出現了有意思的結果——當複製 10 萬條隨機數據時,用老方法還是比新方法快。用 ES6 的擴展運算操作 […arr] 和 Array.from, 加上 ES5 的 map 方法,arr.map(x=>x) 性能都不如老方法 arr.slice() 和 連接方法 [].concat(arr)
Duplicate using Slice, average: ~367 microseconds Duplicate using Map, average: ~469 microseconds Duplicate using Spread, average: ~512 microseconds Duplicate using Conct, average: ~366 microseconds Duplicate using Array From, average: ~1,436 microseconds Duplicate manually, average: ~412 microseconds
3.對象迭代
另一個經常遇到的場景就是對象迭代,通常就是我們不能根據特定的 key取值,而必須遍歷 JSON 結構 或者 Object。我們有老方法 for-in (for(let key in obj)),也有新方法 Object.keys(obj) 和 Object.entries(obj)。
我們用上述方法,對 10 萬個對象,每個對象都包含 1000 個隨機的 keys 和 values 進行性能分析。結果如下:
Object iterate For-In, average: ~240 microseconds Object iterate Keys For Each, average: ~294 microseconds Object iterate Entries For-Of, average: ~535 microseconds
出現這樣結果的原因是,後兩種方案創建了可枚舉的數值組,而不是在沒有 keys 的情況下直接遍曆數組。但是最終的結果仍然值得關注。
結論
我的結論顯而易見——如果性能對你的應用很關鍵,或者你的服務需要處理一些過載,那麼使用酷的,可讀性更高的,更簡潔的方法會對你的應用產生重大的性能影響——可能會慢 10 倍!
之後,在盲目跟隨新趨勢之前,先確保這些新方法是否滿足需求,對於小應用,快速迭代和高可讀性對代碼是完美的,但是對於壓力大的服務器和龐大的客戶端應用,可能不是最佳實踐。
原文:https://hackernoon.com/3-javascript-performance-mistakes-you-should-stop-doing-ebf84b9de95