JS学习——防抖节流

143 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情

前言

防抖节流是常见的面试题,在日常开发过程中我们也会用来优化,理解实现方式并且能够手写出来是我们必须要掌握的,今天我们就来看一下如何手写防抖节流。

防抖

定义

防抖:在事件触发n秒后再执行代码,期间点击一次就会重新计时。防抖常用于能够连续触发事件但只想要执行一次的场景,比如:输入框输入搜索,输入完等待一段时间再进行执行。

实现

防抖的特点是在规定事件触发会重新计时,要想实现这一个功能:

  1. 实现n秒后再运行,通过设置延时器——setTimeout(),delay就是规定的时间。
  2. 闭包写法,为了全局变量的影响,我们将写成闭包形式,return一个函数,函数就是延时器,延时器里面就是我们想要执行的函数fun
  3. this指向问题,在setTimeout中this指向当前的window,当我们执行fn传参时,就需要改变this指向,不然获取不到执行对象。 经过上面三个步骤的考虑我们就能得到防抖函数:
   function debounce(fun, delay) {
      //fun 执行函数 delay 延迟时间
      let timer;
      //写成闭包形式 return一个函数
      return function () {
       const _this = this;
      const args = arguments;
        if (timer) {
          //有定时器清除
          clearTimeout(timer);
        }
        timer = setTimeout(function () {
          //用apply改成this指向,使其指向执行的实例
          fun.apply(_this, args);
        }, delay);
      };
    }

节流

定义

节流:在n秒内多次触发事件,就只会执行一次。比如:用户疯狂点击搜索按钮,如果不做节流处理,会重复向后端发送请求,这种情况可能会导致报错。

实现

节流的特点是n秒内只触发一次,跟着这个思路:

  1. n秒后触发一次,也是一个延迟执行的函数,所以我们还可以使用setTimeout()实现。
  2. 只触发一次,我们可以进行判断,比如setTimeout存在就返回,不去执行;还有一种思路就是时间戳,获取第一次点击的时间戳保存起来,每次点击都获取当前时间戳,两者相减与规定时间做对比,小于规定时间就返回,不去执行。
  3. 闭包形式,节流我们也使用闭包形式的写法。
   //延时器写法
    function throttle1(fun, delay) {
      let timer;
      //写成闭包形式 return一个函数
      return function () {
        const _this = this;
        const args = arguments;
        //首次将timer进行赋值,再次点击后判断为false不会执行
        if (!timer) {
          timer = setTimeout(function () {
            fun.apply(_this, args);
            timer = null; //执行完赋值为null
          }, delay);
        }
      };
    }
    //时间戳写法
    function throttle2(fun, delay) {
      //首次时间
      let firstTime = new Date().getTime();
      return function () {
        //获取当前时间进行对比
        const _this = this;
        const args = arguments;
        const nowTime = new Date().getTime();
        if (nowTime - firstTime >= delay) {
          fun.apply(_this, args);
          firstTime = new Date().getTime(); //执行完重新赋值
        }
      };
    }

总结

防抖就像打游戏时候回城,回城期间再点会重新计算回城时间,适用于连续触发事件,比如监听滚动条事件;节流就像按技能,按多次还是只会释放一次,当用户疯狂点击请求时,可以防止一直发送请求。