如何理解防抖debounce和节流throttle

news/2024/7/19 13:20:39 标签: js, 防抖, 节流

本人通过阅读网络上防抖节流多篇相关的文章,并借鉴相关案例进行说明。

防抖

防抖就像人眨眼睛一样,不可能不停的眨,每隔一定时间眨一下,防止眼睛干涩,如果不停眨眼,别人以为你眼睛有毛病了。
再举一个例子,比如两个人对话,A不停的balabala(持续触发),如果A说话的时候有停顿,但是停顿的时间不够长,B就认为A还没说完,当A停顿时间超过足够长(一定间隔)就认为A说完了,然后B开始说(响应)。

节流

节流就像排队过安检,当人很多的时候(持续触发),安保会隔一段时间放一部分人进行安检(一定间隔)。例如下图这个feel:
<a class=节流" />

区别

要想真正搞懂防抖节流,必须弄懂二者之间的异同。
防抖只会在连续的事件周期结束时执行一次,而节流会在事件周期内按间隔时间有规律的执行多次。

相同之处:

  1. 都是某个行为持续触发;

不同之处:

防抖

  1. 结束完触发;
  2. 无规律;
  3. 周期内触发一次;

节流

  1. 达到一定条件就触发;
  2. 有规律;
  3. 周期内触发多次;
  4. 可以稀释函数触发频率;

巨人的肩膀

先来看看underscore中如何实现防抖节流

js">// Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  _.debounce = function(func, wait, immediate) {
    var timeout, result;

    var later = function(context, args) {
      timeout = null;
      if (args) result = func.apply(context, args);
    };

    var debounced = restArgs(function(args) {
      if (timeout) clearTimeout(timeout);
      if (immediate) {
        var callNow = !timeout;
        timeout = setTimeout(later, wait);
        if (callNow) result = func.apply(this, args);
      } else {
        timeout = _.delay(later, wait, this, args);
      }

      return result;
    });

    debounced.cancel = function() {
      clearTimeout(timeout);
      timeout = null;
    };

    return debounced;
  };
js">// Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time. Normally, the throttled function will run
  // as much as it can, without ever going more than once per `wait` duration;
  // but if you'd like to disable the execution on the leading edge, pass
  // `{leading: false}`. To disable execution on the trailing edge, ditto.
  _.throttle = function(func, wait, options) {
    var timeout, context, args, result;
    var previous = 0;
    if (!options) options = {};

    var later = function() {
      previous = options.leading === false ? 0 : _.now();
      timeout = null;
      result = func.apply(context, args);
      if (!timeout) context = args = null; //显示地释放内存,防止内存泄漏
    };

    var throttled = function() {
      var now = _.now();
      if (!previous && options.leading === false) previous = now;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0 || remaining > wait) {
        if (timeout) {
          clearTimeout(timeout);
          timeout = null;
        }
        previous = now;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      } else if (!timeout && options.trailing !== false) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };

    throttled.cancel = function() {
      clearTimeout(timeout);
      previous = 0;
      timeout = context = args = null;
    };

    return throttled;
  };

大道至简

为了更好的理解,我找了一个精简版的防抖节流

js">function debounce (fn, delay) {
    let timer   = null;

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

        if (timer) {
            clearTimeout(timer);

            timer = setTimeout(function () {
                fn.apply(context, args);
            }, delay);
        } else {
            timer = setTimeout(function () {
                fn.apply(context, args);
            }, delay);
        }
    }
}
js">function throttle (fn, delay) {
   let  timer    = null,
        remaining   = 0,
        previous = new Date();

    return function () {
        let now = new Date(),
        remaining = now - previous,
        args = arguments,
        context = this;

        if (remaining >= delay) {
            if (timer) {
                clearTimeout(timer);
            }

            fn.apply(context, args);
            previous = now;
        } else {
            if (!timer) {
                timer = setTimeout(function () {
                    fn.apply(context, args);
                    previous = new Date();
                }, delay - remaining);
            }
        }
    };
}

彩蛋

贴一个理解起来非常棒的demo案例:http://demo.nimius.net/debounce_throttle/

相关文章

  1. https://www.jianshu.com/p/c8b86b09daf0
  2. https://www.zhangshengrong.com/p/KWa3jQ3w1o/
  3. https://www.cnblogs.com/nanchen/p/7922959.html

http://www.niftyadmin.cn/n/1581248.html

相关文章

1024快乐!浅谈scrollTop需要踩的坑

开始之前&#xff0c;需要分清楚scrollTo和scrollTop 坑one 1.设置浏览器scrollTop 最好通过用户操作设置滚动&#xff0c;或者setTimeout延时滚动 // Chrome和Safari用法一样 window.scrollTo(x, y)&#xff1b;可查看MDN说明。 2.设置元素scrollTop // Chrome和Safari下效…

Flickr看不到照片了

晕倒&#xff0c;看不到照片了&#xff0c;听说是GFW搞的&#xff0c;不知道什么时候弄好。要不要人家看照片啊&#xff01;

如何写出高效的 Vue 代码

开讲之前我先简单的自我介绍一下&#xff0c;本人自喻&#xff1a;flitrue&#xff0c;工作三年有余&#xff0c;在一家不知名的互联网企业担任前端架构师之职。 技术选型问题 近几年前端发展快速&#xff0c;很多同学抱怨学不动了&#xff0c;要回家喂猪。面对前端技术海量的…

最佳的75个网络安全工具 (转载)

工具&#xff1a;Nessus&#xff08;最好的开放源代码风险评估工具&#xff09; 网址&#xff1a;http://www.nessus.org/ 类别&#xff1a;开放源码 平台&#xff1a;Linux/BSD/Unix 简介&#xff1a;Nessus是一款可以运行在Linux、BSD、Solaris以及其他一些系统上的远程安全扫…

深入了解Object.freeze()和Object.seal()

目录Object.freeze()Object.seal()对比Object.freeze()和Object.seal()拓展Object.preventExtensions()Object.freeze() 官方MDN对Object.freeze()的说明&#xff0c;如下&#xff1a; Object.freeze()方法可以冻结一个对象。一个被冻结的对象再也不能被修改&#xff1b;冻结了…

英文总经理室财务部生产部业务部品管部卫生间

GM Office (General Manager Office) Finance Department (Department of Finance) Product Department (Department of Product) Business Department (Department of Business) Production Control Department (Department of Production Control) Rest Room 如果觉得TOILET感…

gulp和webpack的区别

基本区别&#xff1a; gulp可以进行js&#xff0c;htm&#xff0c;css&#xff0c;img的压缩打包&#xff0c;是自动化构建工具&#xff0c;可以将多个js文件或是css压缩成一个文件&#xff0c;并且可以压缩为一行&#xff0c;以此来减少文件体积&#xff0c;加快请求速度和减…

庆祝香港回归10周年

庆祝香港回归10周年 转载于:https://www.cnblogs.com/xA51121/archive/2007/07/01/801752.html