防抖和节流

98 阅读2分钟

一、使用背景

在浏览器中可视窗口大小的改变,窗口的滚动以及输入框的搜索和校验等操作,都会导致操作函数在极短的时间内被触发多次,但是在大部分情况中我们只需要触发一次即可。因而在这种情况下,会加重浏览器的负担,降低用户的体验。因此,我们采用debounce(防抖)和throttle(节流)的方式来减少操作函数触发的频率而又不影响效果。

二、函数防抖

当持续触发事件时,debounce 会合并事件且不会去触发事件当一定时间内没有再触发这个事件时,才真正去触发事件

代码演示:

1.非立即执行版:

触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

function debounce(func, delay) {
  let timer; // 给定时器占个位
  return function () {
    // 关闭上一次开启的定时器
    clearTimeout(timer);
    // 重新设置一个定时器
    timer = setTimeout(() => {
      func.apply(this, arguments);
    }, delay);
  };
}

2.立即执行版:

触发事件后函数会立即执行,然后 n 秒内不再触发事件,然后触发才能继续执行函数的效果。

function debounce(func, delay) {
  let timer; // 给定时器占个位
  return function () {
    // 关闭上一次开启的定时器
    clearTimeout(timer);
    // 第一次触发时定时器的值为null
    let isFirst = !timer;// 定时器被关闭后取反也是true
    // 重新设置一个定时器
    timer = setTimeout(() => {
     // 一段时间后将定时器设为null,不影响下一次
     timer = null;
    }, delay);
    // 若是第一次触发就执行函数
    if(isFirst) func.apply(this,arguments)
  };
}

三、函数节流

当持续触发事件时,保证隔间时间触发一次事件。throttle 会合并一定时间内的事件,限制一个函数在一定时间内内只能执行一次

代码演示:

function throttle(func, delay) {
  let timer;
  return function () {
    // 如果timer存在,就继续执行已经存在的timer
    if (timer) return;
    timer = setTimeout(() => {
      func.apply(this, arguments);
      // 执行完毕后把timer赋值为null,不影响下次
      timer = null;
    }, delay);
  };
}