浅谈js防抖和节流
防抖和节流的重要性
防抖和节流严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死。所以还是很有必要早点掌握的。同时,防抖和节流也是我们闭包当中的一部分,闭包包含了防抖和节流。
防抖(debounce)
场景:我们在写项目当中的搜索功能时,如果我们每输入一个字符就调用一次接口,会导致请求过于频繁,而且请求并没有意义,只有最后一次的调用接口才是有意义的
思路:在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后:
- 如果在200ms内没有再次触发滚动事件,那么就执行函数
- 如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时
效果:如果短时间内大量触发同一事件,只会执行一次函数。
实现: 使用一个setTimeOut计时器,用一个变量来保存时间,考虑维护全局纯净,用一个闭包函数时间:
function debounce(fn,delay){
let timer; //定时器
return function(...args){ //形成闭包
//args 为函数调用时传的参数
let context = this
timer&&clearTimeout(timer) //函数再次执行时,清除定时器,重新开始计算
//利用定时器,让指定函数延迟执行
timer = setTimeout(function(){//执行传入的指定函数,利用apply更改this的绑定和传参
fn.apply(context,args)
},delay)
}
}
以上就是防抖实现了,那么我们可以给出一个定义:
- 对于短时间内连续触发的事件,防抖的含义就是让某个时间期限(如上面的1000毫秒)内,事件处理函数只执行一次。
节流(throttle)
看完防抖之后,我们继续思考,
但是如果产品同学的期望处理方案是:即使用户不断拖动滚动条,也能在某个时间间隔之后给出反馈呢?,这个问题我们还能用防抖来实现吗?当然是不行的,这里我们就需要用到这篇文章的第二个重点:节流
场景:当你需要监听滚动条变化,从而去计算页面中某个元素到窗口顶部距离的时候.
思路:我们可以设计一种类似控制阀门一样定期开放的函数,也就是让函数执行一次后,在某个时间段内暂时失效,过了这段时间后再重新激活(有点类似于技能冷却时间)
效果:如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
function throttle(fn,delay){
let timer; // 定时器
return function(...args){
let context = this;
// 如果timer存在,说明函数还未该执行
if(timer) return;
timer = setTimeout(function(...args){
// 当函数执行时,让timer为null。
timer = null;
fn.apply(context,args);
},delay);
}
}
以上就是节流的实现了,可以我们可以给出一个定义:
- 节流允许我们的一个函数在xxx毫秒之内只执行一次
总结:
以上是我们可以自己使用原生js来封装的防抖和节流代码,我们也可以使用lodash来实现防抖和节流操作,具体网址如下:Lodash 简介 | Lodash 中文文档 | Lodash 中文网 (lodashjs.com)