简单理解js中的防抖和节流
就结果而言,防抖和节流就是为了防止事件在短时间内多次触发而产生的两种解决方案。
防抖
防抖是将多次操作合并为一次来完成操作。其原理就是维护一个定时器,在规定的时间后触发函数;但是在该规定时间内再次触发的话,就会取消之前的定时器,再重新设置,保证了只有最后一次操作能够被触发。具体操作步骤大致为:
- 利用闭包保存一个变量,然后返回一个定时器函数(这个函数就是后续频繁操作触发调用的函数);
- 根据标记条件判断是否第一次需要立即执行(根据使用场景自行设置);
- 当有新的触发操作时,如果存在定时器,则清除该定时器;
- 设定新的定时器,重新计时。
演示代码如下:
function debounce(fnc,times,immediate){
let timer = null;
return function(...args){
// 立即执行操作
if(immediate && !timer){
fnc.apply(this, args);
}
// 清空定时器
timer && clearTimeout(timer);
// 设置新定时器,重新计时
timer = setTimeout(()=>{
fnc.apply(this, args);
},times);
}
}
节流
节流是在规定时间内,只能触发一次操作。就像游戏中释放技能一样,需要一定的等待时间(技能冷却)。节流的实现分为两种:
-
定时器操作:其重点是利用闭包存储 timer定时器变量,具有两个特点:
- n秒后才会执行第一次操作(定时器到达规定时间才会被触发);
- 停止触发操作后还会再执行一次(因为该函数是延迟执行,当停止触发时该函数已经加入到了任务队列中,所以会再执行一次);
function throttle(fn,waiting){ let timer = null; return function(...args){ if(!timer){ timer = setTimeout(()=>{ fn.apply(this, args); timer = null; },waiting) } } }
-
设立时间戳:时间戳版本的节流函数重点是了利用了闭包来记录上一次的触发时间点previous,同样具有两个特点:
- 第一次开始触发就会立即执行(previous的初始值为0);
- 停止触发后不再执行(因此时的函数是同步任务,再被触发时就会进行相应的判断,就不会出现停止后再被触发执行的情况)
function throttle(fn,waiting){ // 上一次的执行时间 let previous = 0; return function(...args){ // 当前时间 let now = +new Date(); if(now - previous > waiting){ previous = now; fn.apply(this, args); } } }
这里是万物之恋,我们下次再见了!