浅谈「节流」与「防抖」函数

497 阅读2分钟

定义:

  • 节流: 函数节流是指某个函数在一个时间段内(如3s)执行了一次,则在这段时间内无论触发多少次都不再执行,直到到下一个时间段再执行;
  • 防抖: 防抖是指每次触发都重置一个等待时间,在这个等待时间内多次触发时,只能在最后一次触发再过一个等待时间时执行一次函数;

举例理解:

举个生活的例子可能更好理解一些:

  • 节流,可以理解为一个画家一天只会画一幅画,即使他半天就能画完,但是他这一天只画这一幅,只能等第二天再画第二幅。

  • 防抖,可以理解为一辆公交车想要关门这个操作,但一直有人要上车,想关门只能等最后一个人上车后5s内没有人还要上车时,才可以关门。

代码实现:

节流简单实现:

const throttle = (fn, wait = 50) => {
  let previous = 0;//闭包存上次触发的时间
  return function(...args) {
    let now = +new Date();
    if (now - previous > wait) {
      previous = now;
      fn.apply(this, args);
    }
  };
};
const betterFn = throttle(() => console.log("fn 函数执行了"), 3000);
setInterval(betterFn, 1000);

解析:

  • throttle高阶函数处理包装入参的函数(() => console.log("fn 函数执行了"));
  • previous 闭包存上次成功执行的时间;
  • betterFn每1秒调用1次,记录当前时间比较是否超过设定时间,如没超过代表触发太频繁了不想执行,如果超过了设定时间,代表距离上次成功执行有一定时间了,允许执行并记录时间到previous;
  • 如果总时间是10s,如上的节流改造后,会在第0s,3s,6s,9s执行4次(暂不考虑定时器不准的因素);

防抖简单实现:

function debounce(fn, wait = 50) {
  let timer = null;
  return function(...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, wait);
  };
}
const betterFn = debounce(() => console.log("fn 防抖执行了"), 1000);
document.addEventListener("mousemove", betterFn);

解析:

  • timer闭包存储定时器,内部函数可以访问到;
  • 高频触发betterFn时,如果有定时器就清掉重新定时,直到设定时间到了才执行函数;
  • 如果一直触发不停下来,那就一直重新计时间,就一直不执行;

应用场景:

  • 一些鼠标滚动事件,鼠标移动事件需要回调函数处理一些业务逻辑,但又想提高性能,不想频繁执行函数导致页面卡死,可以使用;
  • 工具库:underscore.js、lodash.js