JS中惰性函數(shù)的使用小結(jié)
JS中的惰性函數(shù)(Lazy Function)其實是一種非常巧妙的性能優(yōu)化設(shè)計模式,也就是利用js的動態(tài)重寫函數(shù)的思想,用第一次調(diào)用時微乎其微的代價,換取了后續(xù)所有調(diào)用的極致性能,它的核心思想非常直白:讓函數(shù)在第一次執(zhí)行時“記住”環(huán)境特性或計算結(jié)果,并在后續(xù)調(diào)用中直接走捷徑,不再做無意義的重復(fù)判斷或計算。
你可以把它想象成下班回家認路:第一天到一個新小區(qū),你需要停下來辨認方向、確認門牌號(這是第一次執(zhí)行的“臟活累活”);但如果你住了十年,每天回家還在每個路口重新認路就太荒謬了。惰性函數(shù)就是讓你“第一次辛苦認路,以后閉著眼走直線”。
核心原理:函數(shù)自我重寫
在 JavaScript 中,函數(shù)是一等公民,這意味著函數(shù)可以在運行時被重新賦值和修改。惰性函數(shù)正是利用了這一特性,在函數(shù)內(nèi)部將自己重寫為一個優(yōu)化后的“精簡版”函數(shù)。
在 JS 中,實現(xiàn)惰性函數(shù)主要有以下兩種經(jīng)典寫法:
1. 函數(shù)內(nèi)直接重寫(延遲執(zhí)行版)
這種寫法在第一次調(diào)用時才進行環(huán)境檢測和函數(shù)重寫。
function createXHR() {
// 第一次進入這里,做繁重的環(huán)境檢測
if (window.XMLHttpRequest) {
// 如果是標(biāo)準(zhǔn)瀏覽器,將 createXHR 重寫為直接返回新對象的函數(shù)
createXHR = function () {
return new XMLHttpRequest();
};
} else {
// 如果是古董 IE,重寫為兼容版本
createXHR = function () {
return new ActiveXObject("Microsoft.XMLHTTP");
};
}
// 重寫完后,手動調(diào)用一次新函數(shù),保證第一次調(diào)用也能拿到正確的結(jié)果
return createXHR();
}
運行流程: 第一次調(diào)用 createXHR() 時,它進入原函數(shù)體做判斷,把全局的 createXHR 指針指向新函數(shù),然后返回結(jié)果。以后再調(diào)用 createXHR(),它就已經(jīng)是那個精簡版的新函數(shù)了,直接返回結(jié)果,完全跳過了 if/else 判斷。
2. 閉包 + 立即執(zhí)行(立即執(zhí)行版)
這種寫法在代碼加載階段(函數(shù)被賦值時)就立刻執(zhí)行判斷,并返回最終的函數(shù)形態(tài)。
const addEvent = (function () {
// 這個外層自執(zhí)行函數(shù)只跑一遍
if (document.addEventListener) {
// 標(biāo)準(zhǔn)瀏覽器,直接返回優(yōu)化后的函數(shù)
return function (el, type, handler) {
el.addEventListener(type, handler, false);
};
} else if (document.attachEvent) {
// 古董 IE,返回兼容版函數(shù)
return function (el, type, handler) {
el.attachEvent("on" + type, handler);
};
}
})();
運行流程: addEvent 在定義時,外層函數(shù)就立即執(zhí)行并根據(jù)環(huán)境返回了最終形態(tài)。后續(xù)無論調(diào)用多少次 addEvent,它都是最終那個沒有判斷邏輯的函數(shù)。
經(jīng)典應(yīng)用場景
- 瀏覽器兼容性檢測:比如檢測
addEventListener、localStorage或IntersectionObserver等 API 是否存在。因為瀏覽器的運行環(huán)境在頁面打開那一刻就已經(jīng)確定了,不會中途改變,完全沒必要每次調(diào)用都去掃描一遍。 - 單次初始化邏輯:比如生成一次性的復(fù)雜正則表達式、拉取遠程配置后把
init函數(shù)替換成空函數(shù)(防止重復(fù)初始化)。 - 復(fù)雜計算或資源加載緩存:對于一些第一次計算非常耗時的操作,可以在第一次算出結(jié)果后緩存起來,后續(xù)直接返回緩存值。
概念辨析:惰性函數(shù) vs 惰性求值
在學(xué)習(xí)過程中,你可能會遇到另一個相似的概念叫**“惰性求值(Lazy Evaluation)”**。這兩者雖然都帶“惰性”,但解決的問題完全不同:
- 惰性函數(shù)(Lazy Function):側(cè)重于一次判斷,終身受益。通過重寫函數(shù)來消除重復(fù)的條件判斷,提升高頻調(diào)用時的執(zhí)行效率。
- 惰性求值(Lazy Evaluation):側(cè)重于按需計算,節(jié)省資源。通常利用 ES6 的生成器來實現(xiàn),推遲昂貴計算或處理無限數(shù)據(jù)流,只有當(dāng)真正需要某個值時才去計算它(例如處理超大數(shù)組的過濾和映射)。
掌握惰性函數(shù),能讓你在處理跨瀏覽器兼容或高頻工具函數(shù)時,寫出性能更極致、邏輯更優(yōu)雅的代碼。
到此這篇關(guān)于JS中惰性函數(shù)的使用小結(jié)的文章就介紹到這了,更多相關(guān)JS 惰性函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript NaN和Infinity特殊值 [譯]
本文要講的是兩個特殊值,NaN和Infinity,返回這兩個值的操作通常都應(yīng)該返回正常的數(shù)字2012-09-09
JS 循環(huán)li添加點擊事件 (閉包的應(yīng)用)
這篇文章主要介紹了js循環(huán)li添加點擊事件 (閉包的應(yīng)用)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-12-12
原生js操作checkbox用document.getElementById實現(xiàn)
js操作checkbox本人建議用document.getElementById(checkbox_id).checked不推薦使用jquery操作checkbox,感興趣的朋友不要錯過2013-10-10
js判斷樣式className同時增加class或刪除class
用正則表達式判斷多個class之間是否存在真正的class(前后空格的處理)然后增加class刪除class,本文給予實現(xiàn)方法,感興趣的朋友可以了解下,或許對你有所幫助2013-01-01
js實現(xiàn)網(wǎng)站最上邊可關(guān)閉的浮動廣告條代碼
這篇文章主要介紹了js實現(xiàn)網(wǎng)站最上邊可關(guān)閉的浮動廣告條代碼,涉及javascript基于鼠標(biāo)事件操作頁面元素樣式的實現(xiàn)技巧,需要的朋友可以參考下2015-09-09
JS實現(xiàn)逐頁將PDF文件轉(zhuǎn)為圖片格式
這篇文章主要為大家分享了如何通過前端js將pdf文件轉(zhuǎn)為圖片格式,并且支持翻頁預(yù)覽、以及圖片打包下載,文中的示例代碼簡潔易懂,需要的可以參考一下2023-05-05

