在一些年以前性能問題,我們前端開發(fā)能做的還是很有限的;不過隨著 JAVAScript 應(yīng)用越來越復(fù)雜,優(yōu)化 JavaScript 性能的重要性就越發(fā)的凸顯出來了。這里我分享 8 個提高 JavaScript 性能的方法。
入題
1. 盡可能的緩存
我們知道緩存一些資源或者結(jié)果是為了減少再次獲得這些資源所需要的時間,所以這是一條很常見的通識。
有兩種選擇。
- 第一種是使用 JavaScript Cache API,我們可以使用 service worker。
- 第二種是使用 HTTP 協(xié)議緩存。
通過把重復(fù)訪問的對象存儲在用戶定義的變量中,以及在后續(xù)對該對象的引用中使用變量,可以立即實現(xiàn)性能的提升。
2. 延遲不必要的 JS 首屏加載
我們希望頁面的加載時間能不讓用戶焦慮,推遲不必要的 JS 首屏加載是一個很好地方法。
程序中不是所有函數(shù)都需要在頁面的初始加載時就要用到。有很多是用戶必須執(zhí)行某個操作才能執(zhí)行某個函數(shù),那么你可以將該函數(shù)的加載推遲到初始頁面加載之后。
一些通用方法
- 使用 defer 和 async 屬性
- 使用類似 getScript() 方法
- 動態(tài)創(chuàng)建 DOM 方式
- 使用延時器
function loadScript (src, onload) { var scriptTag = document.createElement("script"); scriptTag.src = src; if (typeof onload === "function") { scriptTag.onload = onload; scriptTag.onreadystatechange = function () { if (scriptTag.readyState === 4) { onload(); } } } document.body.AppendChild(scriptTag); } 復(fù)制代碼
3. 刪除未使用的 JavaScript
這個步驟是十分必要的,很多人在不使用某些代碼的時候僅僅只是注釋掉;因為他們生怕產(chǎn)品經(jīng)理又反悔。 其實你刪除這些代碼,不僅會縮短傳輸時間,還會縮短瀏覽器分析和編譯代碼所需的時間。
提供幾點作為參考:
- 未使用的代碼直接刪掉,就算后期產(chǎn)品返回,你也可以在 git 歷史中找回來。
- 一些常用的方法不要在自己寫一遍,團(tuán)隊一定要有一個常用方法的公共庫;公用方法都應(yīng)該寫入這個公共庫,而不是寫在業(yè)務(wù)代碼里面。
- 不要因為一個小功能就引入一個第三方插件/庫,你可以使用模塊化的方式引入,或者自己寫一個類似的方法放在項目的公共庫中。
4. 避免內(nèi)存泄漏
如果內(nèi)存正在泄漏,則加載的頁面將保留越來越多的內(nèi)存,并最終占用設(shè)備的所有可用內(nèi)存并嚴(yán)重影響性能。你可能見過此類故障(并且可能對此類故障感到懊惱),例如輪播。
在 Chrome 開發(fā)者工具中,你可以通過在“Performance ”標(biāo)簽中記錄時間線來分析你的網(wǎng)站是否存在內(nèi)存泄漏。
若內(nèi)存占用基本平穩(wěn),就說明不存在內(nèi)存泄漏,反之便是存在。
幾種常見的內(nèi)存泄漏原因:
- 意外的全局變量
- 沒有銷毀的計時器
- 已經(jīng)刪除的 DOM 還是被引用,(刪除 DOM 后將變量設(shè)值為 null 可以避免這個問題)
5. 避免使用全局變量 & 優(yōu)先使用局部變量
這一點主要是想說定義變量的時候用最近原則,即可以在當(dāng)前作用域定義的變量就一定不要定義在上一級,更不要一股腦的直接定義在全局。也就是縮短作用域鏈的查找長度。
我們知道 JS 查找變量是按照作用域鏈查找的,多查找一層勢必會多一點處理時間。定義在當(dāng)前作用域可以加快代碼的執(zhí)行速度。
當(dāng)作用域丟失時,該作用域的變量將被銷毀。
6. 使用 web workers 處理需要大量執(zhí)行時間的代碼
web workers 使 Web 應(yīng)用程序的主執(zhí)行線程分開的后臺線程中運(yùn)行腳本操作成為可能。這樣做的好處是,可以在單獨(dú)的線程中執(zhí)行費(fèi)力的處理,允許主線程(通常是UI)運(yùn)行,而不會阻塞/減慢速度。
web workers 的幾個使用場景
- 預(yù)取數(shù)據(jù) — 優(yōu)化網(wǎng)站的加載時間,可用 web workers 來提前加載數(shù)據(jù)。
- 輪詢工作
7. 合理使用事件代理
我們知道事件代理可以合并類似的操作,可以直接降低與 DOM 的交互。使用事件代理的優(yōu)點就可想而知了:
- 節(jié)約內(nèi)存空間,性能自然提升(合并的函數(shù)占用內(nèi)存比優(yōu)化前少多了)
- 減少 DOM 操作(優(yōu)化性能,減少 DOM 操作一直很重要,這也是 Virtual Dom 流行的幾個基本原因)
8. 將重復(fù)的代碼一定抽象成函數(shù)
我們在寫代碼的時候,有一些代碼會在很多模塊中出現(xiàn)。有些人會覺得不以為然,這樣不會消耗太多的性能,也就沒有抽象出來。
其實這是必要的,這樣做的目的是:
- 是你的項目具有更高的可讀性和擴(kuò)展性,并且團(tuán)隊協(xié)作更加融洽
- 減少代碼的解析和編譯的時間
其他
還有一些諸如代碼壓縮、使用 CDN、合并代碼、Gzip、減少 HTTP 請求、DOM操作優(yōu)化、圖片優(yōu)化等也是優(yōu)化性能的常見方法,不過這些都更加偏向前端工程一些。所以這里只是總結(jié)了一些優(yōu)化 JavaScript 代碼性能的方法。