防抖和节流
防抖
概念:老实说,第一次听到这个词的时候觉得真的太生动了,我想大家从字面上就能get到他的意思。比如说点击出鼠标的时候不小心手抖了,一下子快速点了两次,但如果函数本身只需要触发一次,这样就导致了不确定的结果,所以,防抖的作用是限制函数在一定时间内只能触发一次,防止你”手抖“。当然这个手抖可能是无意的,也可能是网页防止你恶意的行为。
常见的处理手法是闭包和定时器:
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触发时,闭包检查定时器是否存在,存在的话把原定时器清除,然后设置新的定时器。
但从程序合理性去考虑,如果用户不断点击,这样事件触发就不断延后,虽然应该没有那么无聊的人,但这样的做法始终还是有他的不合理性。因此我做了以下的改动
1 function debounce(fn,wait){ 2 var timer = null; 3 return function(){ 4 if(timer === null){ 5 timer = setTimeout(()=>{ 6 fn() 7 clearTimeout(timer) 8 timer = null 9 },wait) 10 } 11 } 12 } 13 14 function handle(){ 15 console.log(Math.random()); 16 } 17 18 window.addEventListener("click",debounce(handle,1000))
这样的话事件触发就不会延后了,并且也起到了防抖的效果。
需要防抖的场景还有很多,比如resize,onscroll,click,input等。
节流:
概念:节流的作用不同于防抖,防抖的话是一定时间内触发多次只执行一次,而节流是当短时间触发多次时,把这几次触发间隔一定的时间,当触发的函数需要操作dom和进行很大量的数据操作和计算,或者异步请求时候,节流可以起到防止丢帧和卡顿的效果。
示例:
1 function throttle(fn,delay){ 2 let valid = true 3 return function() { 4 if(!valid){ 5 //休息时间 暂不接客 6 return false 7 } 8 // 工作时间,执行函数并且在间隔期内把状态位设为无效 9 valid = false 10 setTimeout(() => { 11 fn() 12 valid = true; 13 }, delay) 14 } 15 } 16 /* 请注意,节流函数并不止上面这种实现方案, 17 例如可以完全不借助setTimeout,可以把状态位换成时间戳,然后利用时间戳差值是否大于指定间隔时间来做判定。 18 也可以直接将setTimeout的返回的标记当做判断条件-判断当前定时器是否存在,如果存在表示还在冷却,并且在执行fn之后消除定时器表示激活,原理都一样 19 */ 20 21 function showTop () { 22 var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; 23 console.log('滚动条位置:' + scrollTop); 24 } 25 window.onscroll = throttle(showTop,1000)