詳解JS函數防抖
一、什么是函數防抖
概念:函數防抖(debounce),就是指觸發事件后,在 n 秒內函數只能執行一次,如果觸發事件后在 n 秒內又觸發了事件,則會重新計算函數延執行時間。
舉個栗子,坐電梯的時候,如果電梯檢測到有人進來(觸發事件),就會多等待 10 秒,此時如果又有人進來(10秒之內重復觸發事件),那么電梯就會再多等待 10 秒。在上述例子中,電梯在檢測到有人進入 10 秒鐘之后,才會關閉電梯門開始運行,因此,“函數防抖”的關鍵在于,在 一個事件 發生 一定時間 之后,才執行 特定動作。
二、為什么需要函數防抖
前端開發過程中,有一些事件,常見的例如,onresize,scroll,mousemove ,mousehover 等,會被頻繁觸發(短時間內多次觸發),不做限制的話,有可能一秒之內執行幾十次、幾百次,如果在這些函數內部執行了其他函數,尤其是執行了操作 DOM 的函數(瀏覽器操作 DOM 是很耗費性能的),那不僅會浪費計算機資源,還會降低程序運行速度,甚至造成瀏覽器卡死、崩潰。這種問題顯然是致命的。
除此之外,短時間內重復的 ajax 調用不僅會造成數據關系的混亂,還會造成網絡擁塞,增加服務器壓力,顯然這個問題也是需要解決的。
三、函數防抖如何解決上述問題
根據上面對問題的分析,細細思索,可以想到如下解決方案。
函數防抖的要點,是需要一個 setTimeout 來輔助實現,延遲運行需要執行的代碼。如果方法多次觸發,則把上次記錄的延遲執行代碼用 clearTimeout 清掉,重新開始計時。若計時期間事件沒有被重新觸發,等延遲時間計時完畢,則執行目標代碼。
四、函數防抖的代碼實現
根據以上分析,我們對 “函數防抖” 來進行簡單的代碼實現,如下:
function debounce(fn,wait){ var timer = null; return function(){ if(timer !== null){ clearTimeout(timer); } timer = setTimeout(fn,wait); }} function handle(){ console.log(Math.random());} window.addEventListener('resize',debounce(handle,1000));
五、函數節流的使用場景
函數防抖一般用在什么情況之下呢?一般用在,連續的事件只需觸發一次回調的場合。具體有:
搜索框搜索輸入。只需用戶最后一次輸入完,再發送請求;
用戶名、手機號、郵箱輸入驗證;
瀏覽器窗口大小改變后,只需窗口調整完后,再執行 resize 事件中的代碼,防止重復渲染。
目前遇到過的用處就是這些,理解了原理與實現思路,小伙伴可以把它運用在任何需要的場合,提高代碼質量。
總結
函數防抖其實是分為 “立即執行版” 和 “非立即執行版” 的,根據字面意思就可以發現他們的差別,所謂立即執行版就是 觸發事件后函數不會立即執行,而是在 n 秒后執行,如果在 n 秒內又觸發了事件,則會重新計算函數執行時間。 而 “非立即執行版” 指的是 觸發事件后函數會立即執行,然后 n 秒內不觸發事件才能繼續執行函數的效果。。
在開發過程中,我們需要根據不同的場景來決定我們需要使用哪一個版本的防抖函數,一般來講上述的防抖函數都能滿足大部分的場景需求。但我們也可以將非立即執行版和立即執行版的防抖函數結合起來,實現最終的雙劍合璧版本的防抖函數,以下為小伙伴們做了簡單的實現:
/*** @desc 函數防抖---“立即執行版本” 和 “非立即執行版本” 的組合版本* @param func 需要執行的函數* @param wait 延遲執行時間(毫秒)* @param immediate---true 表立即執行,false 表非立即執行**/function debounce(func,wait,immediate) {let timer;return function () {let context = this;let args = arguments;if (timer) clearTimeout(timer);if (immediate) {var callNow = !timer;timer = setTimeout(() => {timer = null;}, wait)if (callNow) func.apply(context, args)} else {timer = setTimeout(function(){func.apply(context, args)}, wait);}}}function handle(){console.log(Math.random());}// window.addEventListener('mousemove',debounce(handle,1000,true)); // 調用立即執行版本window.addEventListener('mousemove',debounce(handle,1000,false)); // 調用非立即執行版本
以上就是詳解JS函數防抖的詳細內容,更多關于JS函數防抖的資料請關注好吧啦網其它相關文章!
相關文章: