簡單復(fù)習(xí)下什么是JavaScript的防抖和節(jié)流

來源 | https://www.cnblogs.com/echoyya/p/14565642.html
函數(shù)節(jié)流和函數(shù)防抖,兩者都是優(yōu)化高頻率執(zhí)行js代碼的一種手段。
以監(jiān)聽頁面滾動為例,分別看一下普通滾動,函數(shù)節(jié)流,函數(shù)防抖三者的實現(xiàn)效果。

函數(shù)節(jié)流
比如人眨眼睛,就是一定時間內(nèi)眨一次。 再比如就是游戲中的技能CD,按下技能以后,再規(guī)定的時間內(nèi),你再按也沒用,只能冷卻好了再按。
// 函數(shù)防抖var timer = false;document.getElementById("debounce").onscroll = function(){clearTimeout(timer); // 清除未執(zhí)行的代碼,重置回初始化狀態(tài)timer = setTimeout(function(){console.log("函數(shù)防抖");}, 1000);};
函數(shù)防抖的要點:也需要一個定時器來輔助實現(xiàn)代碼延遲執(zhí)行。如果計時未完之前,方法被多次觸發(fā),則清除上次記錄的定時器標(biāo)記,重新開始。
若計時完畢,沒有繼續(xù)觸發(fā)方法,則執(zhí)行邏輯代碼。
監(jiān)聽id = debounce元素的滾動事件,首先就是清除上次未執(zhí)行的setTimeout的引用timer
clearTimeout方法,允許傳入無效的值。所以直接執(zhí)行clearTimeout即可。
將需要執(zhí)行的代碼放入setTimeout定時器中,再返回定時器引用給timer緩存。
如果倒計時結(jié)束,沒有新的方法觸發(fā)滾動事件,則執(zhí)行setTimeout中的代碼。
函數(shù)防抖的原理,就是巧用setTimeout做緩存池,并且可以輕易地清除待執(zhí)行代碼。
函數(shù)防抖
函數(shù)防抖,是指觸發(fā)高頻事件n秒后函數(shù)會執(zhí)行一次,如果n秒內(nèi)高頻事件被再次觸發(fā),則重新計算時間;在整個過程中,事件函數(shù)只會被執(zhí)行一次。
比如坐公交,在一定時間內(nèi),如果有人陸續(xù)刷卡上車,司機就不會開車。只有沒有人再刷卡了,司機才開車。
再比如游戲中的buff,吃了bull,開始倒計時,此時又吃了一個buff,則重新記時。
使用場景:click、onMouseOver,onMouseMove,resize,input,scroll等
// 函數(shù)節(jié)流var canRun = true;document.getElementById("throttle").onscroll = function(){if(!canRun){// 判斷是否已空閑,如果在執(zhí)行中,則直接returnreturn;}canRun = false;setTimeout(function(){console.log("函數(shù)節(jié)流");canRun = true;}, 1000);}
監(jiān)聽id = throttle元素的滾動事件。當(dāng)canRun為true,代表當(dāng)前滾動處理事件是空閑的,可以使用。然后下一步的操作就是canRun=false。這樣其他請求執(zhí)行滾動事件的方法,就被return。 setTimeout設(shè)置1000ms時間間隔,執(zhí)行定時器中的回調(diào)函數(shù),釋放標(biāo)志位,允許執(zhí)行下一次滾動事件。 若具體執(zhí)行的方法是一個回調(diào)函數(shù),也可以將canRun=true放到callback中。只要理解了函數(shù)節(jié)流基本原理,改造就會得心應(yīng)手。
學(xué)習(xí)更多技能
請點擊下方公眾號
