嫌JS寫得不夠好?我教你??!五個小技巧
1. 緩存——localStorage和sessionStorage
localStorage和sessionStorage是現(xiàn)代web開發(fā)非常好用的功能。二者到底是什么呢?我們看看mdn上對他們的介紹
“These mechanisms are available via the Window.sessionStorage and Window.localStorage properties (to be more precise, in supporting browsers the Window object implements the WindowLocalStorage and WindowSessionStorage objects, which the localStorage and sessionStorage properties hang off) — invoking one of these will create an instance of the Storage object, through which data items can be set, retrieved and removed. A different Storage object is used for the sessionStorage and localStorage for each origin — they function and are controlled separately.”
大概意思是——這些機制可以通過Window使用。sessionStorage和窗口。localStorage屬性(更準確地說,在支持的瀏覽器窗口對象實現(xiàn)了WindowLocalStorage和WindowSessionStorage對象,localStorage和sessionStorage屬性掛斷電話)調(diào)用其中的一個將創(chuàng)建存儲對象的一個實例,通過這些數(shù)據(jù)項可以設置、檢索和刪除。不同的Storage對象用于sessionStorage和localStorage,它們分別起作用和控制。
說了一大堆其實用起來很簡單,設置key和value存在瀏覽器緩存文件中下次可以再用。

雖然緩存很好用,但是這些API是同步的。也就是說,調(diào)用這個接口的時候主線程會被占用。此外,不管是localStorage還是sessionStorage都只能存字符串。用的時候記得要序列化和反序列化(JSON.parse和JSON.stringify)
舉例:
const startTime = performance.now();const testData = Array(1000).fill(true);store datalocalStorage.setItem('foo', JSON.stringify(testData));retrieve dataconst storedData = JSON.parse(localStorage.getItem('foo'));const endTime = performance.now();console.log(`time ${endTime - startTime} ms.`);
在多次調(diào)用的情況下會發(fā)現(xiàn)有明顯的卡頓。這是因為讀取緩存IO操作會有較大的性能開銷,多次IO操作導致卡頓。
這個時候可以在內(nèi)存中做個緩存,比如:
const cache = {};export const getStorageValue = (key) = {if (cache[key]) {return cache[key];}const value = localStorage.getItem(key);return value === null value JSON.parse(value);};export const setStorageValue = (key string, value unknown) = {cache[key] = value;localStorage.setItem(key, JSON.stringify(value));};
可以解決一部分問題,當然具體使用場景要具體分析。
2. 使用web的Observe API
有時候,會有這樣這樣一個場景:有一個滾動的窗口,你要監(jiān)聽某些元素是否在屏幕某個位置。一般情況下,你是要監(jiān)聽scroll事件,然后在進行一些計算來判斷是否滿足條件。scroll事件不斷觸發(fā),你需要不斷計算,此時又合適用防抖來減少性能消耗,節(jié)流可能可以,但是,有沒有更好的辦法呢?有,那就是 Observe API
比如,IntersectionObserver,MutationObserver,ResizeObserver,分別用在是否可見,HTML文檔是否被更改,元素的邊框或者尺寸是否被修改。
(瀏覽器兼容性如下圖,可以看到除了IE以外主流瀏覽器都是支持的)

3.接受提前返回
用if寫判斷并返回一個值的時候,我們經(jīng)常給返回的值先存在一個變量中,等到所有判斷結(jié)束后再統(tǒng)一返回這個變量,比如:
function calItem(i) {let result = undefined;if (i % 15== 0) {result = 'FizzBuzz';} else if (i % 3 == 0) {result = 'Fizz';} else if (i % 5 == 0) {result = 'Buzz';} else {result = i;}return result;}
其實,沒必要。
在這種簡單的情況下,可以直接返回終止函數(shù)。
function calcItem(i) {if (i % 15 == 0) {return 'FizzBuzz';}if (i % 3 == 0) {return 'Fizz';}return (i % 5 == 0) 'Buzz' i;}
這樣看起來也更清爽,易懂,好改。
我知道,在某些關(guān)于code refactor或是一些基礎教程中建議你按照上面的寫法,一個函數(shù)只有一個出口比較方便,尤其是在C語言這種命令式語言中。但是在Js中我們經(jīng)常不斷拆分復雜函數(shù),使得每個功能塊盡可能短,在這種情況下,可以說,沒必要。直接返回,干凈清爽。
書是死的,人是活的。照著死規(guī)矩一成不變才是大忌。切記。
4.掌握 Async 和 Defer
你的頁面里,script是怎么解析是非常重要的一件事情。用戶進到你的網(wǎng)站后,script的解析處于競爭狀態(tài),所以你得了解你的script按照什么順序執(zhí)行才行,不然可能會有意想不到的Bug。
有三個選項:default,async,還有defer。default是默認的意思。得到script,執(zhí)行。此時解析度進程會暫停,直到你腳本執(zhí)行好后再繼續(xù)。async,異步。頁面解析和腳本執(zhí)行同時進行。defer,等待。腳本則在頁面解析完成后才開始。

理解什么時候腳本被執(zhí)行非常重要。
根據(jù)經(jīng)驗,相互之間沒有依賴的腳本標記async并行執(zhí)行就好了。有依賴的話標上defer依次執(zhí)行。
5.推遲非立即需要執(zhí)行的任務
JavaScript是單線程異步的。所以有哪些代碼不需要馬上執(zhí)行的,可以推遲點執(zhí)行。降低優(yōu)先級,讓資源先用在高優(yōu)先級的地方。
怎么操作呢?
有個好東西叫requestIdleCallback??纯碝DN是怎么介紹的
“The window.requestIdleCallback() method queues a function to be called during a browser’s idle periods. This enables developers to perform background and low priority work on the main event loop, without impacting latency-critical events such as animation and input response.” — MDN Web Docs
大概是說,requestidlecallback()方法將在瀏覽器空閑期間調(diào)用的函數(shù)排成隊列。這使得開發(fā)人員能夠在主事件循環(huán)上執(zhí)行后臺和低優(yōu)先級的工作,而不會影響延遲關(guān)鍵事件,如動畫和輸入響應。
可以在許多情況下應用此策略。其中最常見的是發(fā)送分析信息。我們不介意數(shù)據(jù)是早到還是晚到。這是一個非關(guān)鍵任務,因為它將由另一個服務異步處理。
比如:
const handleId = window.requestIdleCallback(() = {Analytics.sendEvent('purchaseProduct'....);}, {timeout 2000});
在這個例子中,我們將等待瀏覽器空閑時來執(zhí)行我們的Analytics代碼。如果這在接下來的兩秒內(nèi)沒有發(fā)生,它無論如何都會被執(zhí)行。超時時間為可選選項。它可以幫助您進一步定制代碼的執(zhí)行。如果該選項不存在,它只會在瀏覽器有時間時執(zhí)行。
以上5個JS 小技巧,如果您認為對您有幫助,請記得 點贊、留言、分享和收藏 哦~~
