函数防抖与节流是很相似的概念,但它们的应用场景不太一样。
我们先从概念上深刻理解它们。
概念
函数防抖(debounce)
函数防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
简单的说,当一个动作连续触发,则只执行最后一次。
如果有人进电梯(触发事件),那电梯将在10秒钟后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时)
函数节流(throttle)
限制一个函数在一定时间内只能执行一次。
保证如果电梯第一个人进来后,10秒后准时运送一次,这个时间从第一个人上电梯开始计时,不等待,如果没有人,则不运行
应用场景
函数防抖的应用场景
连续的事件,只需触发一次回调的场景有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
函数节流的应用场景
间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 谷歌搜索框,搜索联想功能
- 高频点击提交,表单重复提交
函数防抖(debounce)
函数防抖的简单实现:
function _debounce(fn,wait){
var timer = null;
return function(){
clearTimeout(timer) // 清除未执行的代码,重置回初始化状态
timer = setTimeout(()=>{
fn()
},wait)
}
}
function fn(){
console.log(1)
}
window.onscroll = _debounce(fn,500)()
函数防抖在执行目标方法时,会等待一段时间。当又执行相同方法时,若前一个定时任务未执行完,则 clear 掉定时任务,重新定时。
函数节流(throttle)
1)函数节流的 setTimeout 版简单实现
function _throttle(fn, time) {
let timer, firstTime = true;
return function (){
if(firstTime) {
fn();
firstTime = false
}
if(timer){return false}
timer = setTimeout(function(){
clearTimeout(timer)
fn();
timer = null
},500)
}
}
function fn(){
console.log(1)
}
window.onscroll = _throttle(fn,500)()
函数节流的目的,是为了限制函数一段时间内只能执行一次。因此,通过使用定时任务,延时方法执行。在延时的时间内,方法若被触发,则直接退出方法。从而,实现函数一段时间内只执行一次。
2)函数节流的时间戳版简单实现
根据函数节流的原理,我们也可以不依赖 setTimeout实现函数节流。
1 function _throttle(fn, wait){
2 let last = 0;
3 return () => {
4 const current_time = +new Date();
5 if (current_time - last > wait) {
6 fn.apply(this, arguments);
7 last = +new Date();
8 }
9 };
10 };
11 function fn(){
12 console.log(1)
13 }
14 window.onscroll = _throttle(fn,500)()
其实现原理,通过比对上一次执行时间与本次执行时间的时间差与间隔时间的大小关系,来判断是否执行函数。若时间差大于间隔时间,则立刻执行一次函数。并更新上一次执行时间。
异同比较
相同点:
- 都可以通过使用 setTimeout 实现。
- 目的都是,降低回调执行频率。节省计算资源。
不同点:
-
函数防抖,在一段连续操作结束后,处理回调,利用 clearTimeout 和 setTimeout 实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。
-
函数防抖关注一定时间连续触发,只在最后执行一次,而函数节流侧重于一段时间内只执行一次。
参考文献:
https://www.cnblogs.com/8023-CHD/p/11398969.html