防抖和节流

什么是防抖(Debounce)?

短时间内连续触发多次事件(用户点击/鼠标移动/键盘事件/鼠标滚轮等),只执行最后一次, 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

javascript 复制代码
      var btn = document.getElementById("btn");
      btn.onclick = debounce(() => {
        console.log("防抖执行了");
      }, 1000);
      
      //封装防抖函数(debounce)
      function debounce(fn, wait) {
        let timer = null;
        return function () {
          let _this = this;
          let args = arguments;
          // 每次点击时都是先关在开,永远保证当前只有一个正在执行的定时器
          if (timer) {
            clearTimeout(timer);
          }
          timer = setTimeout(function () {
            fn.apply(_this, args);
          }, wait);
          console.log(timer); 
        };
      }

下图是控制台的输出情况:

可以发现,只有当用户停止点击后,才会触发fn()函数,打印"防抖执行了"语句,每次产生新的触发,都会覆盖旧有触发的定时器,并重新计时,即多次点击只有计最后一次有效

什么是节流(Throttle)?

在一个单位时间内,连续多次事件触发,只执行第一次。短时间内连续触发多次事件,会减少执行次数。达到稀释函数执行频率的效果。 可以将节流函数看作一个闸门,一旦有事件触发,就立即关闭闸门,不让其他事件进入,直到进入的事件响应结束,才再次开放闸门。

1.用定时器实现:

javascript 复制代码
      var btn = document.getElementById("btn"); 
      btn.onclick = throttle(() => { console.log("节流函数执行"); }, 1000);
      
      function throttle(fn, wait) {
        let timer = null;
        return function () {
          let _this = this;
          let _args = arguments;

          if (!timer) {   //若当前没有正在执行的定时器
            timer = setTimeout(function () {
              timer = null;
              fn.apply(_this, _args);
            }, wait); //只有当定时器将wait时间走完,timer才会再次被赋值null,才可再次进入if语句
          }
          console.log(timer);
        };
      }

2.用时间戳实现

javascript 复制代码
     function throttle1(fn, wait) {
        let time = 0;
        return function () {
          let _this = this;
          let _args = arguments;
          
          let now = Date.now();
          //相邻两次点击的时间间隔大于需要wait的时间,即上一单位时间内事件已响应完毕
          if (now - time > wait) { 
            fn.apply(_this, _args);
            time = now;
          }
        };

下图是控制台的输出情况:

可以发现,与防抖函数不同,当用户多次点击时,实际响应的始终是第一次点击时的定时器。只至定时器将需要wait的时间走完,打印了"节流函数执行"。即单位时间内,多次触发仅执行第一次。

防抖和节流的异同

相同点:

  1. 作用都是为了降低回调函数触发频率,减小计算负担。
  2. 都是基于一次性定时器setTimeout实现的,并运用闭包进行封装。

区别:

防抖函数多次触发只执行最后一次,节流函数多次触发只执行第一次。

触发频率不同,实际上防抖函数比节流函数更为"严格",防抖在单位时间s内永远只执行最后一次,而节流函数函数则可执行s/wait(向下取整)次。

例如,防抖和节流函数定时器的wait时间均为500ms,那么在5s内,防抖函数仅触发最后一次,而节流函数将触发10次。

防抖和节流的使用场景

防抖(适合仅需一次生效的场景)

  1. 登录,发送验证码,限时秒杀等按钮,用户短时间内多次点击,仅最后一次响应并发送请求
  2. search搜索时,等待用户结束输入后,再发送请求。
  3. windows触发resize时,会频繁进行计算调整窗口大小,用防抖节约计算资源。

节流(适合隔一段时间执行一次场景)

  1. 滚动监听,例如下拉加载,触底加载等
  2. 搜索框的搜索联想功能
相关推荐
regon12 分钟前
第九章 述职11 交叉面试
面试·职场和发展·《打造卓越团队》
LYFlied17 分钟前
【每日算法】LeetCode 105. 从前序与中序遍历序列构造二叉树
数据结构·算法·leetcode·面试·职场和发展
gis分享者1 小时前
如何在 Shell 脚本中如何使用条件判断语句?(中等)
面试·shell·脚本·语法·使用·判断·条件
LYFlied2 小时前
【每日算法】LeetCode 114. 二叉树展开为链表:从树结构到线性结构的优雅转换
数据结构·算法·leetcode·链表·面试·职场和发展
Q741_1472 小时前
Linux 进程核心解析 fork()详解 多进程的创建与回收 C++
linux·c++·面试·笔试·进程
牛客企业服务2 小时前
AI面试:如何从概念真正落地?
人工智能·面试·职场和发展
铭哥的编程日记2 小时前
后端面试通关笔记:从真题到思路(me)
笔记·面试·职场和发展
写写闲篇儿11 小时前
微软面试之白板做题
面试·职场和发展
敲敲了个代码12 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web
liang_jy13 小时前
Android LaunchMode
android·面试