描述
两个点击按钮
点击第一个按钮:用防抖效果执行函数fn1。
点击第二个按钮:用节流效果执行函数fn2。
函数fn1和fn2为 具体的业务操作,如请求操作。
基础功能
<body>
<button id="btn1">点击实现防抖</button>
<button id="btn2">点击实现节流</button>
<script>
const btn1 = document.getElementById('btn1')
const btn2 = document.getElementById('btn2')
function fn1(){
console.log('用防抖效果 调用事务fn1');
console.log(this);
}
function fn2(){
console.log(new Date());//查看间隔时间
console.log('用节流效果 调用事务fn2');
console.log(this);
}
//防抖
btn1.addEventListener('click',debounce(fn1,2000))
//节流
btn2.addEventListener('click',throttle(fn2,2000))
</script>
</body>
防抖
比如6秒内一直触发事件,都不会执行fun函数,当第6秒 停止 触发后,间隔2秒后才执行fun,也就是8秒后执行。如果第7秒又触发事件,则重新计时,如果当即停下2秒后也就是第9秒执行,如果一直触发事件,就一直不会执行fun函数。直到停止触发后2秒内再有触发才会执行一次fun函数。
理解:相当于回城,一直点击回城,只会以最后一次点击为准回城。
function debounce(fun,delay){
let timer;
return function(){
clearTimeout (timer);
timer = setTimeout(()=>{
fun.call(this);
},delay)
}
}
节流
第一次点击时,timer为空 ,跳过if(timer) return。给timer 添加定时器,这个定时器,2秒后才执行函数。在2秒内 ,不管点击多少次,timer都不为空,直接return ,当点击第10次时是在两秒后,已知在两秒时执行了函数并且设为null,所以点击的这个第10次,又给timer添加了定时器。
如果6秒内一直触发,会每隔两秒执行调用fun函数,第2秒执行一次,第4秒执行一次,第6秒执行一次。
当第7秒触发后停下,则第8秒时最后一次调用。
理解:相当于攻速,低攻速无论点多块,都只按照 低攻速的频率发起攻击。
function throttle(fun,delay){
console.log(new Date());//查看间隔时间
let timer;
return function(){
if(timer) return;
timer = setTimeout(()=>{
fun.call(this);
timer = null
},delay)
}
}
注意this指向问题
function debounce(fun,delay){
//初始化就执行了debounce,只初始化一次timer。每次点击就是执行 return内容。
let timer;
return function(){
//let timer;如果在return内 停下来2000毫秒后会陆续执行所有的事件触发
//因为每次点击的执行函数都是独立的,所以清除函数没有起到作用
//要让这些独立的执行函数之间有联系,就利用到作用域链,把timer放在return外面,每次clear都是同一个timer
clearTimeout (timer);
let _this = this;
let args = arguments;
timer = setTimeout(function(){
// fun();//这里回调执行已经在window下了
fun.call(_this,args);
},delay)
}
}