JavaScript 防抖和节流
一、防抖
1-1 防抖基本概念
防抖具体指的是某个函数在某段时间内,无论触发了多少次回调,都只执行最后一次。假如我们设置了一个等待时间 3 秒的函数,在这 3 秒内如果遇到函数调用请求就重新计时 3 秒,直至新的 3 秒内没有函数调用请求,此时执行函数,不然就以此类推重新计时
1-2 防抖实现原理
防抖实现原理就是利用定时器,函数第一次执行时设定一个定时器,并且通过闭包缓存起来,之后调用时发现已经设定过定时器就清空之前的定时器,并重新设定一个新的定时器,如果存在没有被清空的定时器,当定时器计时结束后触发函数执行。
/*
* 防抖函数
* @param fn 事件触发的操作
* @param delay 多少毫秒内连续触发事件,不会执行
* @returns {Function}
*/
function debounce(fn,delay) {
let timer = null; //通过闭包缓存了一个定时器
return function () {
const args = [...arguments];
const that = this
timer && clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(that,args);
},delay);
}
}
window.onscroll = debounce(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},200)
二、节流
2-1 节流基本概念
函数节流指的是某个函数在一定时间间隔内(例如 3 秒)只执行一次,在这 3 秒内 无视后来产生的函数调用请求,也不会延长时间间隔。3 秒间隔结束后第一次遇到新的函数调用会触发执行,然后在这新的 3 秒内依旧无视后来产生的函数调用请求,以此类推。函数节流非常适用于函数被频繁调用的场景,例如:window.onresize() 事件、mousemove 事件、上传进度等情况。
2-2 节流实现原理
实现原理就是通过一个布尔类型变量来判断是否可执行回调,当变量为true时,生成一个定时器,同时将变量取反通过闭包保存起来,当定时器执行完回调后,再将变量变为true,在变量为期false间,调用节流函数不会生成定时器。
/**
* 节流函数
* @param fn 事件触发的操作
* @param delay 间隔多少毫秒需要触发一次事件
* @returns {Function}
*/
function throttle(fn, delay) {
let flag = true;
return function () {
if (!flag) {
return;
}
const that = this
const args = [...arguments];
flag = false;
setTimeout(() => {
fn.apply(that, args);
flag = true;
}, delay);
}
}
window.onscroll = debounce(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},200)
三、使用场景
在一些高频率事件触发的场景下我们不希望对应的事件处理函数多次执行的时候,可以使用防抖和节流,比如:
- 滚动事件
- 输入的模糊搜索
- 轮播图切换
- 点击操作......
浏览器默认情况下都会有自己的监听时间间隔(以谷歌浏览器为例,大概在4-6毫秒,就会去监听一下事件是否有发生),如果检测到多次事件的监听执行,那么就会造成不必要的资源浪费)