Contents

防抖与节流

防抖与节流是一种基于闭包优化高频率执行 js 代码的一种方法, 例如处理一些如 scroll、mousemove、mouseover 等触发时会不断地调用绑定的事件处理回调函数, 极大地浪费资源, 降低前端性能. 所以为了优化体验, 需要对这类事件进行调用次数的限制.

防抖

当在函数被触发 n 秒后再执行回调, 如果在这 n 秒内又被触发, 则重新计时.

简单实现的防抖函数

function debounce(fn, delay) {
  let timer;
  return function (...args) {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

我们在 body 上设置一个 mousemove 事件, 在用户鼠标停留 500ms 后输出用户鼠标最终停留的位置

function printPosition(event) {
  console.log('x ->', event.offsetX);
  console.log('y ->', event.offsetY);
}

// 在用户鼠标停留 500ms 后输出
document.body.addEventListener('mousemove', debounce(printPosition, 500));

当用户在 500ms 内移动了鼠标, debounce 机会使用 clearTimeout 移除定时器, 并重新开始计时, 直到用户鼠标停留了 500ms 才输出用户的鼠标位置

节流

每隔一段时间, 只执行一次函数, 这就是节流函数

函数节流的目的, 是为了限制函数一段时间内只能执行一次. 当函数在延迟时间内被重复运行, 则直接退出, 直到延迟结束才能再次运行.

简单实现的节流函数, 请注意节流与防抖的差异

function throttle(fn, delay) {
  let timer;
  return function (...args) {
    // 当函数在运行时, timer 是存在的, 这时直接退出即为节流函数, 重置定时器就是防抖函数
    if (timer) {
      return;
    }
    timer = setTimeout(() => {
      fn.apply(this, args);
      timer = null;
    }, delay);
  };
}

这在防止表单重复提交时非常有效

function submit() {
  // TODO: submit something
}

const el = document.querySelector('#submit');
el.addEventListener('click', throttle(submit, 1000));

参考链接

浅析函数防抖与函数节流