手寫節流函式
阿新 • • 發佈:2021-10-23
節流原理
如果持續的觸發事件,每隔一段時間,只執行一次事件
應用場景
- DOM元素的拖拽功能實現
- 射擊遊戲
- 計算滑鼠移動的距離
- 監聽scroll滾動事件
underscore中的防抖函式_.throttle
contant.onmousemove = _.throttle(doSomeThing, 2000, {
leading: false, //禁用首次執行,即禁用第一次呼叫事件函式立即執行
trailing: false //禁用最後一次執行
//二者不能都為false,將會產生bug
});
防抖函式實現原理:時間戳 + 定時器
1. 時間戳實現
第一次觸發,最後一次不觸發 { leading:true, training: false }
function throttle(func, wait){ let context, args; //之前的時間戳 let old = 0; return function(){ context = this; args = arguments; //獲取當前時間戳 let now = new Date().valueOf(); if(now-old > wait){ // 立即執行 func.apply(context,args); old = now; } } }
2. 定時器實現
第一次不觸發,最後一次觸發{ leading:false, training: true }
function throttle(func, wait){ let context, args, timeout; return function(){ context = this; args = arguments; if(!timeout){ timeout = setTimeout(()=>{ timeout = null; func.apply(context,args); },wait) } } }
3.時間戳+定時器
function throttle(func, wait, options){
let context, args, timeout;
let old = 0; //時間戳
if(!options) options = {};
let later = function() {
old = new Date().valueOf();
timeout = null;
func.apply(context,args);
}
return function(){
context = this;
args = arguments;
let now = new Date().valueOf();
if(options.leading === false){
old = now;
}
if(now-old > wait){
//第一次直接執行
if(timeout){
clearTimeout(timeout);
timeout = null;
}
func.apply(context, args);
old = now;
}else if(!timeout && options.trailing !== false){
//最後一次會執行
timeout = setTimeout(later, wait);
}
}
}