碼文不易,轉載請帶上本文連結,感謝~ https://www.cnblogs.com/echoyya/p/14565642.html
函式節流和函式防抖,兩者都是優化高頻率執行js程式碼的一種手段。
以監聽頁面滾動為例,分別看一下普通滾動
,函式節流
,函式防抖
三者的實現效果。
函式節流
函式節流:是指在高頻事件觸發期間,n秒內函式只會執行一次。
- 比如人眨眼睛,就是一定時間內眨一次。
- 再比如就是遊戲中的技能CD,按下技能以後,再規定的時間內,你再按也沒用,只能冷卻好了再按。
使用場景:click
、onMouseOver
,onMouseMove
,resize
,input
,scroll
等
// 函式防抖
var timer = false;
document.getElementById("debounce").onscroll = function(){
clearTimeout(timer); // 清除未執行的程式碼,重置回初始化狀態
timer = setTimeout(function(){
console.log("函式防抖");
}, 1000);
};
函式防抖的要點:也需要一個定時器來輔助實現程式碼延遲執行。如果計時未完之前,方法被多次觸發,則清除上次記錄的定時器標記,重新開始。若計時完畢,沒有繼續觸發方法,則執行邏輯程式碼。
-
監聽
id = debounce
元素的滾動事件,首先就是清除上次未執行的setTimeout
的引用timer
-
clearTimeout
方法,允許傳入無效的值。所以直接執行clearTimeout
即可。 -
將需要執行的程式碼放入setTimeout定時器中,再返回定時器引用給
timer
快取。 -
如果倒數計時結束,沒有新的方法觸發滾動事件,則執行
setTimeout
中的程式碼。 -
函式防抖的原理,就是巧用
setTimeout
做快取池,並且可以輕易地清除待執行程式碼。
函式防抖
函式防抖:是指觸發高頻事件n秒後函式會執行一次,如果n秒內高頻事件被再次觸發,則重新計算時間;在整個過程中,事件函式只會被執行一次。
- 比如坐公交,在一定時間內,如果有人陸續刷卡上車,司機就不會開車。只有沒有人再刷卡了,司機才開車。
- 再比如遊戲中的buff,吃了bull,開始倒數計時,此時又吃了一個buff,則重新記時。
使用場景:click
、onMouseOver
,onMouseMove
,resize
,input
,scroll
等
// 函式節流
var canRun = true;
document.getElementById("throttle").onscroll = function(){
if(!canRun){
// 判斷是否已空閒,如果在執行中,則直接return
return;
}
canRun = false;
setTimeout(function(){
console.log("函式節流");
canRun = true;
}, 1000);
}
函式節流的要點:宣告一個標誌位,設定執行的時間間隔,記錄當前程式碼是否在執行,如果空閒,則可以正常觸發方法執行,反之則取消這次方法執行,直接return
。
-
監聽
id = throttle
元素的滾動事件。當canRun
為true
,代表當前滾動處理事件是空閒的,可以使用。然後下一步的操作就是canRun=false
。這樣其他請求執行滾動事件的方法,就被return。 -
setTimeout
設定1000ms時間間隔,執行定時器中的回撥函式,釋放標誌位,允許執行下一次滾動事件。 -
若具體執行的方法是一個回撥函式,也可以將
canRun=true
放到callback
中。只要理解了函式節流基本原理,改造就會得心應手。