js防抖和节流的源码实现

18 阅读2分钟

什么时候用防抖,是在高频事件触发结束一段时间后,再去执行回调,否则在这段时间内再次触发,就会重新计时。

——————防抖——————

举例子是进电梯,一直进人电梯就一直关不上门,等一段时间没人进来才能关闭电梯门

再比如:

1、联想词,等用户输入完一段时间不动后,才被认为是输入结束

2、页面滚动加载,等滚动停止一段时间后,再去加载下一页,不然就会一直去触发

3、按钮点击多次防止重复提交,停止频繁点击后再提交

function debounce(cb, ms) {
  let timer = null;
  return function () {
    // 如果存在定时器说明还有任务在执行,清除重置
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      timer = null;
      clearTimeout(timer);
      cb();
    }, ms);
  };
}
const handleResize = () => {
  console.log("执行事件");
};
window.addEventListener("resize", debounce(handleResize, 2000));

写代码时我犯了两个错误,

第一个直接在debounce(handleResize, 2000)的handleResize处写了箭头函数, 这样会立即执行该函数,要写函数的引用,不是函数本身,函数参数会去立即执行的。

第二个错误是debounce函数没有返回函数,错了,因为addEventListener监听事件要写函数回调才会去执行

——————节流——————

节流主要注意频率问题,需要隔段时间执行一次的就需要节流。

比如说,鼠标移动追踪,每100ms去追踪一次,以及游戏技能冷却等

function throttle(cb, ms) {
  // 如果触发了怎么办,发现在上一个事件设置的timer还在,说明时间没到,不触发
  let timer = null;
  return function (...args) { // args可以捕获事件触发时传递的所有参数
    if (timer) return;
    timer = setTimeout(() => {
      cb.apply(this, args);
      timer = null;
    }, ms);
  };
}
const handleMove = (event) => {
  console.log("移动", event.clientX, event.clientY);
};
window.addEventListener("mousemove", throttle(handleMove, 2000));

cb.apply(this, args);这句需要拿出来单独说一下,其实也可以就这么写cb(...args) 主要是看回调函数cb中有没有需要用到修改this指向的地方。

完。。。