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

