一、两者共同点和不同点
1.共同点
- 都使用了闭包减少全局变量
- 都可以使用setTimeout函数实现
- 都是为了降低回调函数执行频率节省计算资源
2.不同点
防抖在事件发生后执行回调,节流在事件持续发生过程中按照一定时间间隔执行回调。
二、防抖
是指一个动作在一个规定时间内只能执行一次,如果在这段时间内触发了多次,其余的会被忽略。
1.使用场景
使用场景:
- 在搜索查询过程中,用户在输入过程中会触发Input值的改变会持续触发函数的调用。搜索框实时搜索,只在用户输入最后一次完成后,才会执行搜索。
- 窗口大小需要调整时,只记录最后一次的调整变化,防止浏览器多次重绘Dom。
2.特点
防抖是在事件停止触发一段时间后执行回调,且回调只会执行一次。往往是等待某种操作停止后,加以间隔进行操作。
- 持续触发不执行。
- 不触发的一段时间之后再执行。
3.实现
搜索框实时搜索应用场景:用户持续操作时不执行,停止操作500毫秒后调用 ,其中需要注意this的指向问题,开始由于setTimeout回调函数中this指向window,需要用call改变其指向,指向inp,使用闭包封装防抖函数减少了全局变量。
let inp = document.querySelector('input');
inp.oninput = debounce(function() {
console.log(this.value);
}, 500) //间隔500毫秒执行打印输出
//利用闭包封装一个防抖的方法
function debounce(fn, delay) {
t = null;
return function() {
if (t !== null) {
clearTimeout(t)
}
t = setTimeout(() => {
fn.call(this); //将this指向从window转为inp,输出用户输入内容
}, delay)
}
}
三、节流
指的是定义一个固定频率,只允许动作按照我们规定的频率触发,如果用户连续触发该动作,在频率以内的动作会被忽略。
1.使用场景
用户在商品搜索页滑动浏览商品的时候,若我们监听了窗口滚动发送埋点请求的话,就会频繁的触发接口调用。为了限制用户短时间内持续操作,频繁触发接口调用,我们可以借助节流方法。
2.特点
节流是在事件持续触发时,以一定的时间间隔去定时执行回调。
3.实现
使用场景:滚到底部加载更多,防止用户多次滑动而发起请求,设置一个常量flag,当一次滚动回调结束,就修改flag值为false停止执行回调 ,若检测到用户仍在滚动屏幕,则再次调用回调函数
window.onscroll = throttle(function() {
console.log('hello');
}, 500)
function throttle(fn, delay) {
let flag = true;
return function() {
if (flag) {
setTimeout(() => {
fn.call(this);
flag = true;
}, delay)
}
flag = false;//当一次滚动回调结束,就修改flag值为false停止执行回调 ,若仍在滚动屏幕,则再次调用回调函数
}
}