防抖和节流

什么是防抖(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. 搜索框的搜索联想功能
相关推荐
Xiao Fei Xiangζั͡ޓއއ40 分钟前
一觉睡醒,全世界计算机水平下降100倍,而我却精通C语言——scanf函数
c语言·开发语言·笔记·程序人生·面试·蓝桥杯·学习方法
NMBG221 小时前
[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
java·开发语言·面试·java-ee·intellij-idea
刘艳兵的学习博客7 小时前
刘艳兵-DBA033-如下那种应用场景符合Oracle ROWID存储规则?
服务器·数据库·oracle·面试·刘艳兵
用户31574760813518 小时前
成为程序员的必经之路” Git “,你学会了吗?
面试·github·全栈
布川ku子19 小时前
[2024最新] java八股文实用版(附带原理)---Mysql篇
java·mysql·面试
有趣的杰克1 天前
移动端【01】面试系统的MVVM重构实践
面试·职场和发展·重构
saturday-yh1 天前
性能优化、安全
前端·面试·性能优化
前进别停留2 天前
206面试题(71~80)
面试
不二人生2 天前
SQL面试题——飞猪SQL面试 重点用户
数据库·sql·面试
dream_ready2 天前
四万字长文SpringBoot、Spring、SpringMVC等相关面试题(注:该篇博客将会持续维护 最新维护时间:2024年11月12日)
java·spring boot·后端·spring·面试·1024程序员节