前端性能優化- JS篇

前端性能優化- JS篇

前端發展到今天,各種東西層出不窮,樣式以及功能也越發的複雜。但是作為一個前端工作者,我們所需要關注的不僅僅是樣式和功能也需要關注相關的性能優化,因為在功能和樣式都越發豐富的今天,一個好的優化能帶來的作用還是比較顯著的。試想,如果一個頁面的加載速度極慢,還會有多少人會願意瀏覽下去,就算網站的內容很豐富或者特效很炫

從用戶的角度來看,好的優化能夠讓頁面加載得更快、頁面響應更加及時,能夠給用戶帶來更的體驗。從運營者的角度來看,好的優化意味著減少頁面請求數、減小請求所佔帶寬,進而直接影響成本

加載優化

  • 靜態資源緩存
當瀏覽器發送請求時,可以檢測該資源的最新版本是否存在於本地,若存在,則不進行重新加載
  • 靜態資源的優化
可以利用例如webpack等相關工具進行資源的壓縮優化,可以大大減小資源的大小,實現頁面更快的加載 

  • 代碼壓縮
壓縮後的代碼更小,實現頁面更快的加載
  • SSR後端優化
使用SSR進行後端渲染,將數據直接輸入到HTML中,而不需要先下載HTML頁面,再執行AJAX獲取服務器端的數據
  • CDN加載資源
CDN可以做到對不同的區域進行不同的網絡加載優化,從而使資源的加載速度更快,進而頁面的加載速度更快

渲染優化

瀏覽器遇到語義解釋性的JS標籤嵌入文件,那麼此時IE的下載過程會啟用單獨連接進行下載,並在下載後繼續進行解析。並且只有在JS文件解析完成並且加載完後才會繼續往下解析(瀏覽器阻塞)

  • 將JS的執行順序延後
- 將JS放在body的最後面它就不會影響頁面DOM的加載,可以等到頁面都加載完畢後在進行js
- 使用windows.onload事件,它會在頁面執行完之後執行JS
- DOMContentLoaded該事件也是頁面執行完成後觸發,但是它的頁面執行完不包括視頻和圖片,可能圖片或者視頻比較大,但是通常html文件都比較小,所以加載速度通常都會比較快,使用DOMContentLoaded可以提高性能和用戶體驗
  • defer && async
- defer 
瀏覽器在遇到有defer標籤的JS時,仍然會加載JS文件但是不會執行。會等到DOM加載完畢後在執行,可以把它看做成onload
- async
它的作用是能夠異步的加載和執行腳本,不因為加載腳本而阻塞頁面的加載。瀏覽器在遇到有defer標籤的JS會立刻執行加載JS並且一旦JS加載完成就會立即執行,所以很有可能不是按照原本的順序來執行的。在使用async屬性的時候需要慎重,因為它會在加載完成的時候立即觸發,所以並不會安裝特定的執行順序執行,如果JS文件之間有相互依賴的問題就很有可能會出現問題

DOM操作優化

DOM操作是一項非常耗費內存的操作
- 儘量避免多餘的DOM操作,減少重排和重匯的次數。
- 當我們要批量修改DOM節點的時候,我們可以將DOM節點隱藏掉,然後進行一系列的修改操作,之後再將其設置為可見,這樣可以減少頁面的重排
- 使用requestAnimationFrame代替setInterval操作
- 刪除DOM節點的時候,必須要刪除掉節點上的事件,如果不刪除事件會導致內存無法回收,節點上的事件內存佔用並不會隨著DOM的刪除而釋放內存
- 使用innerHTML創建DOM。對於DOM更改,使用innerHTML要比使用標準的DOM方法創建同樣的DOM結構快得多
- 使用事件代理
當一個頁面上的事件過多時,就會直接影響到整體的性能,事件委託就是將目標節點的事件移到父節點來處理,由於瀏覽器冒泡的特點,當目標節點觸發了該事件的時候,父節點也會觸發該事件。因此,由父節點來負責監聽和處理該事件
- 使用JS創建的DOM必須append到頁面中,否則內存不會回收

垃圾收集

在日常中存在在某些情況下垃圾回收機制無法正常的執行,導致內存使用率不斷增高,從而影響JS性能。當數據使用後並且沒有其它作用時,我們可以手動將值設為null來解除引用,從而釋放內存 

函數節流和去抖

反覆重複的調用一個函數將會對性能有特別大的損耗,
- 節流
函數按照一個週期執行,在週期內只多次觸發函數仍就只會執行一次
- 去抖
當事件觸發之後,必須等待某一個時間(N)之後,回調函數才會執行,假若再等待的時間內,事件又觸發了則重新再等待時間N,直到事件N內事件不被觸發,那麼最後一次觸發過了事件N後,執行函數

其他

  • 刪除未使用的代碼
刪除未使用的代碼可以縮小JS的大小,從而加快加載速度
  • 避免全局變量
局部變量的查找速度比全局變量更快。
避免不必要的變量的使用
  • 儘量少用with
with語句會創建自己的作用域,會增加其中執行代碼的作用域鏈的長度
  • 循環優化
- 減值迭代
大多數循環使用一個從0開始、增加到某個特定值的迭代器,在很多情況下,從最大值開始,在循環中不斷減值的迭代器更加高效。
- 簡化終止條件
由於每次循環過程都會計算終止條件,所以必須保證它儘可能快,也就是說避免屬性查找或者其它的操作,最好是將循環控制量保存到局部變量中,也就是說對數組或列表對象的遍歷時,提前將length保存到局部變量中,避免在循環的每一步重複取值。
- 簡化循環體
循環體是執行最多的,所以要確保其被最大限度的優化
- 使用後測試循環
在JavaScript中,我們可以使用for(;;),while(),for(in)三種循環,事實上,這三種循環中for(in)的效率極差,因為他需要查詢散列鍵,只要可以,就應該儘量少用。for(;;)和while循環,while循環的效率要優於for(;;),可能是因為for(;;)結構的問題,需要經常跳轉回去。

  • 最小化訪問nodeList對象
最小化訪問NodeList的次數可以極大的改進腳本的性能

https://segmentfault.com/a/1190000015635431

https://juejin.im/post/5b89274de51d4538c17e0f7d

https://juejin.im/post/5ada1b9f518825673b61946d

https://juejin.im/post/5c6e064c51882562eb50fc18


分享到:


相關文章: