javascript
14个JavaScript代码优化技巧
云棲號資訊:【點擊查看更多行業(yè)資訊】
在這里您可以找到不同行業(yè)的第一手的上云資訊,還在等什么,快來!
JavaScript 已經(jīng)成為有史以來最受歡迎的編程語言之一。根據(jù) W3Tech 的數(shù)據(jù),全世界將近 96%的網(wǎng)站都在使用它。關(guān)于 Web 有一個關(guān)鍵的事實是,你無法控制訪問網(wǎng)站的用戶所用設(shè)備的硬件規(guī)格。最終用戶訪問你的網(wǎng)站時,使用的可能是高端設(shè)備也可能是低端設(shè)備,網(wǎng)絡(luò)連接條件也有好有差。這意味著你必須盡可能優(yōu)化自己的網(wǎng)站,以滿足任何用戶的需求。
這篇文章列舉了一些技巧,可幫助你寫出更好的 JavaScript 代碼,從而提高性能。
附帶提一下,請共享和重用你的 JS 組件,以在高質(zhì)量代碼(寫起來需要花費時間)和合理的交付時間之間保持適當(dāng)?shù)钠胶狻D憧梢允褂?Bit 等流行工具將任何項目中的組件(普通 JS、TS、React、Vue 等)共享到 Bit 的組件中心,用不了多大功夫。
1、刪除未使用的代碼和功能
你的應(yīng)用程序包含的代碼越多,就需要將更多的數(shù)據(jù)傳輸?shù)娇蛻舳恕g覽器也需要更多時間來分析和解釋代碼。
有時,你可能打包了很多根本用不到的功能。最好只在開發(fā)環(huán)境中保留這些額外的代碼,而不要將其推送到生產(chǎn)環(huán)境中,以免給客戶端的瀏覽器增加負(fù)擔(dān)。
要不斷問自己,某個功能或代碼段是否是必要的。
你可以手動移除未使用的代碼,也可以使用 Uglify 或谷歌的 Closure Compiler 之類的工具刪除它們。你甚至可以使用一種稱為搖樹優(yōu)化的技術(shù)從應(yīng)用程序中刪除未使用的代碼。Webpack 這類打包軟件提供了這種技術(shù),詳情可以參考這里。如果要刪除未使用的npm 軟件包,可以使用命令npm prune,詳細(xì)信息參考 NPM 文檔。
2、盡可能緩存
緩存可以減少延遲和網(wǎng)絡(luò)流量,從而減少了顯示資源表示所需的時間,以提高網(wǎng)站的速度和性能。緩存可以借助 Cache API 或 HTTP caching 來實現(xiàn)。你可能想知道內(nèi)容更改時會發(fā)生什么。當(dāng)滿足某些條件(例如發(fā)布新內(nèi)容)時,上述緩存機(jī)制能夠處理和重新生成緩存。
3、避免內(nèi)存泄漏
作為一種高級語言,JS 會負(fù)責(zé)一些底層管理工作,例如內(nèi)存管理。垃圾回收是大多數(shù)編程語言共有的過程。用外行術(shù)語來說,垃圾收集就是收集并釋放已分配給對象,但目前尚未在程序的任何部分中使用的內(nèi)存。在 C 這樣的編程語言中,開發(fā)人員必須使用 malloc() 和 dealloc() 函數(shù)來處理內(nèi)存分配和釋放操作。
雖然在 JavaScript 中垃圾回收是自動執(zhí)行的,但在某些情況下它也不是完美的。在 JavaScript ES6 中,引入了 Map 和 Set 及其“weaker”的同級對象。被稱為 WeakMap 和 WeakSet 的“較弱”對應(yīng)項持有對對象的“弱”引用。它們使未引用的值能夠被垃圾回收,從而防止內(nèi)存泄漏。你可以在此處閱讀有關(guān) WeakMaps 的更多信息。
4、盡早打破循環(huán)
超大循環(huán)肯定會消耗很多寶貴的時間,所以你應(yīng)該盡早打破它們。你可以用 break 關(guān)鍵字和 continue 關(guān)鍵字來做這件事。編寫最高效的代碼是你的責(zé)任。
在下面的示例中,如果你沒有從循環(huán)中 break,則你的代碼將循環(huán)運(yùn)行 1000000000 次,顯然會過載的。
在下面的示例中,如果你在循環(huán)不符合你的條件時沒??有 continue,則你仍將運(yùn)行該函數(shù) 1000000000 次。我們僅在數(shù)組元素處于偶數(shù)位置時處理它。這將循環(huán)執(zhí)行減少了近一半。
let arr = new Array(1000000000).fill('----'); arr[970] = 'found'; for (let i = 0; i < arr.length; i++) {if(i%2!=0){continue;};process(arr[i]); }你可以在此處詳細(xì)了解循環(huán)和性能的關(guān)系。
5、最小化變量計算的次數(shù)
為了減少計算變量的次數(shù),可以使用閉包。通俗來說,JavaScript 中的閉包使你可以從內(nèi)部函數(shù)訪問外部函數(shù)作用域。每次創(chuàng)建函數(shù)(不調(diào)用)時都會創(chuàng)建閉包。內(nèi)部函數(shù)將有權(quán)訪問外部作用域的變量,即使在返回外部函數(shù)之后也是如此。
我們來看兩個例子。這些示例均來自 Bret 的博客。
如果你多次調(diào)用上面的函數(shù),那么每次都會創(chuàng)建一個新對象。每次調(diào)用時,變量 texasCustomers 和 californiaCustomers 都會導(dǎo)致不必要的內(nèi)存重分配。
function findCustomerCity() {const texasCustomers = ['John', 'Ludwig', 'Kate']; const californiaCustomers = ['Wade', 'Lucie','Kylie'];return name => texasCustomers.includes(name) ? 'Texas' : californiaCustomers.includes(name) ? 'California' : 'Unknown'; }; let cityOfCustomer = findCustomerCity(); cityOfCustomer('John');//Texas cityOfCustomer('Wade');//California cityOfCustomer('Max');//Unknown在上面的示例中,借助于閉包,返回到變量 cityOfCustomer 的內(nèi)部函數(shù)可以訪問外部函數(shù) findCustomerCity() 的常量。而且,每當(dāng)以傳遞的名稱作為參數(shù)調(diào)用內(nèi)部函數(shù)時,都無需再次實例化常量。要了解關(guān)于閉包的更多信息,建議你閱讀 Prashant 的博客文章。
6、盡量減少 DOM 訪問
與其他 JavaScript 語句相比,訪問 DOM 的速度很慢。如果你對 DOM 進(jìn)行更改,觸發(fā)了布局的重新繪制,那么就得等好一陣子了。
為了減少訪問 DOM 元素的次數(shù),請先訪問一次,然后將其用作局部變量。完成需求后,請一定將其設(shè)置為 null 來移除該變量的值。這將防止內(nèi)存泄漏,因為這會觸發(fā)垃圾回收過程。
7、壓縮文件
通過壓縮方法(例如 Gzip)可以減小 JavaScript 文件的大小。較小的文件會提升你的網(wǎng)站性能,因為瀏覽器只需下載較小的資產(chǎn)即可。
這類壓縮手段最多可以減少 80%的文件大小。在此處閱讀有關(guān)壓縮的更多信息。
8、縮小最終代碼
有人認(rèn)為縮小和壓縮是相同的,其實不然。在壓縮中,我們使用特殊算法來改變文件的輸出大小;在縮小時,我們需要刪除 JavaScript 文件中的注釋和多余的空格。可以在網(wǎng)上找到許多工具和軟件包來幫助完成這一過程。縮小已成為頁面優(yōu)化的標(biāo)準(zhǔn)做法,也是前端優(yōu)化的主要步驟之一。
縮小可以讓文件大小最多減少 60%。你可以在此處閱讀有關(guān)縮小的更多信息。
9、使用 Throttle(節(jié)流)和 Debounce(防抖)
我們可以使用這兩種技術(shù)來嚴(yán)格控制代碼需要處理事件的次數(shù)。
節(jié)流是指定函數(shù)可以超時的最大次數(shù)。例如,“每 1000 毫秒最多執(zhí)行一次 onkeyup 事件函數(shù)”。也就是說哪怕你每秒敲 20 個鍵,該事件每秒也只會觸發(fā)一次。這將減少代碼的負(fù)擔(dān)。
另一方面,防抖是指定自上次執(zhí)行相同函數(shù)以來再次運(yùn)行該函數(shù)的最短持續(xù)時間。換句話說,“上次調(diào)用函數(shù)后過最少 600 毫秒才執(zhí)行此函數(shù)”。要了解有關(guān)節(jié)流和防抖的更多信息,這里有一篇快速入門。
你可以實現(xiàn)自己的防抖和節(jié)流函數(shù),也可以從Lodash 和Underscore 之類的庫中導(dǎo)入它們。
10、避免使用 Delete 關(guān)鍵字
delete 關(guān)鍵字用于從對象中刪除屬性。這個關(guān)鍵字的性能表現(xiàn)不怎么好,預(yù)計它將在未來的更新中修復(fù)。
或者,你可以簡單地將不需要的屬性設(shè)置為 undefined。
你還可以使用 Map 對象,Bret 認(rèn)為它的 delete 方法會更快。
11、使用異步代碼防止線程阻塞
你應(yīng)該知道 JavaScript 默認(rèn)情況下是同步的和單線程的。但是在某些情況下,你的代碼需要很大的計算量。代碼本質(zhì)上是同步的,意味著一段代碼運(yùn)行時將阻止其他代碼語句運(yùn)行,直到前者完成執(zhí)行為止。這會降低整體性能。
但是我們可以通過異步代碼來避免這種情況。異步代碼以前以回調(diào)的形式編寫,但是 ES6 引入了一種處理異步代碼的新樣式。這種新樣式被稱為 Promise。你可以在 MDN 的官方文檔中了解有關(guān)回調(diào)和 Promise 的更多信息。
可是等等……
JavaScript 默認(rèn)情況下是同步的,并且也是單線程的。
如何在單個線程上運(yùn)行異步代碼呢?這是很多人感到困惑的地方。做到這一點,主要依賴運(yùn)行在瀏覽器后臺的 JavaScript 引擎。JavaScript 引擎是執(zhí)行 JavaScript 代碼的計算機(jī)程序或解釋器。JavaScript 引擎可以用多種語言編寫。例如,支持 Chrome 瀏覽器的 V8 引擎是用 C++ 編寫的,而支持 Firefox 瀏覽器的 SpiderMonkey 引擎是用 C 和 C++ 編寫的。
這些 JavaScript 引擎可以在后臺處理任務(wù)。根據(jù) Brian 的說法,調(diào)用棧可以識別 Web API 的函數(shù),并將其交給瀏覽器處理。瀏覽器完成這些任務(wù)后,它們將返回并作為回調(diào)被推上堆棧。
你可能想知道 Node.js 是怎么做這些工作的,畢竟它沒有瀏覽器的幫助。實際上,支持 Chrome 的那個 V8 引擎也是 Node.js 背后的支撐。這里有 Salil 的一篇很棒的博客文章,解釋了Node 生態(tài)系統(tǒng)中的這一過程。
12、使用代碼拆分
如果你有使用 Google Light House 的經(jīng)驗,肯定會熟悉一種稱為“first contentful paint”的指標(biāo)。它是 Lighthouse 報告的 Performance 部分中跟蹤的六個指標(biāo)之一。
First Contentful Paint(FCP)衡量用戶轉(zhuǎn)到你的頁面后瀏覽器渲染第一段 DOM 內(nèi)容所花費的時間。頁面上的圖像、非白色元素和 SVG 被視為 DOM 內(nèi)容;iframe 內(nèi)部不包含任何內(nèi)容。
獲得更高的 FCP 分?jǐn)?shù)的最佳方法之一是使用代碼拆分。代碼拆分是一種在傳輸開始時僅將必要的模塊發(fā)送給用戶的技術(shù)。通過減小最初發(fā)送的載荷大小,這將極大地影響 FCP 分?jǐn)?shù)。
流行的模塊打包器(例如 webpack)可為你提供代碼拆分功能。你還可以利用原生 ES 模塊來單獨加載各個模塊。你可以在此處詳細(xì)了解有關(guān)原生 ES 模塊的信息。
13、使用 async 和 defer
在現(xiàn)代網(wǎng)站中,腳本比 HTML 更為密集,其大小更大且消耗更多的處理時間。默認(rèn)情況下,瀏覽器必須等待腳本下載和執(zhí)行完畢后,再處理頁面的其余部分。
于是笨重的腳本可能會阻止網(wǎng)頁的加載。為了避免這種情況,JavaScript 為我們提供了兩種分別稱為 async 和 defer 的技術(shù)。你只需將這些屬性添加到
14、使用 Web Workers 在后臺運(yùn)行 CPU 密集型任務(wù)
Web Worker 允許你在后臺線程中運(yùn)行腳本。如果你有一些高強(qiáng)度的任務(wù),可以將它們分配給 Web Worker,這些 WebWorker 可以在不干擾用戶界面的情況下運(yùn)行它們。創(chuàng)建后,Web Worker 可以將消息發(fā)布到該代碼指定的事件處理程序來與 JavaScript 代碼通信,反之亦然。
要了解有關(guān) Web Worker 的更多信息,建議你閱讀 MDN 文檔。
感謝閱讀,歡迎評論,編程愉快!
【云棲號在線課堂】每天都有產(chǎn)品技術(shù)專家分享!
課程地址:https://yqh.aliyun.com/zhibo
立即加入社群,與專家面對面,及時了解課程最新動態(tài)!
【云棲號在線課堂 社群】https://c.tb.cn/F3.Z8gvnK
原文發(fā)布時間:2020-07-21
本文作者:Mahdhi Rezvi
本文來自:“InfoQ”,了解相關(guān)信息可以關(guān)注“InfoQ”
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的14个JavaScript代码优化技巧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么DevOps的必然趋势是BizDe
- 下一篇: Linux系统诊断-内存基础