防抖和节流

防抖和节流

防抖和节流是 JavaScript 开发中性能优化的重要方案, 下面通过代码教你掌握他们.

防抖

当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。

function debounce(fun, delay) {
  let timer = null;
  return function(args) {
    let that = this;
    let _args = args;
    clearTimeout(timer);
    timer = setTimeout(function() {
      fun.call(that, _args);
    }, delay);
  };
}

立即防抖和非立即防抖

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

非立即执行

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

立即执行

下面是一个综合版的例子。

function debounce(func, wait, immediate) {
  var timeout;

  return function() {
    var context = this;
    var args = arguments;

    if (timeout) clearTimeout(timeout);
    if (immediate) {
      var callNow = !timeout;
      timeout = setTimeout(function() {
        timeout = null;
      }, wait);
      if (callNow) func.apply(context, args);
    } else {
      timeout = setTimeout(function() {
        func.apply(context, args);
      }, wait);
    }
  };
}

使用场景

  • search 搜索联想,用户在不断输入值时,用防抖来节约请求资源

  • window 触发 resize 的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次

节流

当持续触发事件时,保证一定时间段内只调用一次事件处理函数。

function throttle(fn, delay) {
  let canRun = true;
  return function() {
    if (!canRun) {
      return;
    }
    canRun = false;
    setTimeout(() => {
      fn.call(this, arguments);
      canRun = true;
    }, delay);
  };
}

节流分为时间戳版和定时器版,下面是一个综合版。

function throttle(func, delay) {
  var timer = null;
  var startTime = Date.now();
  return function() {
    var curTime = Date.now();
    var remaining = delay - (curTime - startTime);
    var context = this;
    var args = arguments;
    clearTimeout(timer);
    if (remaining <= 0) {
      func.apply(context, args);
      startTime = Date.now();
    } else {
      timer = setTimeout(func, remaining);
    }
  };
}

使用场景

  • 鼠标不断点击触发,mousedown(单位时间内只触发一次)

  • 监听滚动事件,比如是否滑到底部自动加载更多,用 throttle 来判断

防抖和节流

参考

7 分钟理解 JS 的节流、防抖及使用场景

JS 的防抖与节流

剖析 requestAnimationFrame

PREVIOUS POST

剖析 requestAnimationFrame

回到顶部的几种玩法

NEXT POST

回到顶部的几种玩法