防抖 + 节流(requestAnimationFrame方式)

2,933 阅读1分钟

title: debounce & throttle

categories: [JS]

tags: []

date: 2021/1/11

请实现一下防抖和节流

防抖函数

debounce 函数返回一个可执行函数。这个可执行函数的作用域链上保存了定时器变量。当重复执行的时候,会先清空掉上次生成的定时器,从而实现延迟执行的效果

代码实现

function debounce(func, wait) {
  let timer = null;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, wait);
  };
}

节流函数

原理与 防抖函数相同,通过 closure 存储上次执行的时间戳,当前时间戳和之前的时间戳相比较,如果超过约定时间,则执行一次函数。

代码实现

时间戳实现
// 只有当上一次调用的时间 与 现在时间的差值 超过了设定的时间 才会再次调用
function throttle(func, interval) {
  let lastTimeStamp = 0;
  return function () {
    let curDate = Date.now();
    const diff = curDate - lastTimeStamp;
    if (diff > interval) {
      func.apply(this, arguments);
      lastTimeStamp = curDate;
    }
  };
}
requestAnimationFrame 实现

参考了 ElementUI 图片拖拽部分的源码

实现原理和时间戳实现方法相同,只不过吧延迟 interval 替换为一帧。在屏幕刷新率为 60HZ 的情况下约为 16.7ms 执行一次(1000ms / 60 = 16.666...ms)

function rafThrottle(func) {
  let lock = false;
  return function (...args) {
    if (lock) return;
    lock = true;
    window.requestAnimationFrame(() => {
      func.apply(this, args);
      lock = false;
    });
  };
}