面试官最喜欢问的防抖和节流怎么手写实现?

465 阅读2分钟

前言

防抖和节流是面试官最喜欢问的问题之一,那么我们怎么手写实现它们呢?下面我们一起来探究!

防抖(Debounce)

防抖是指在触发一次函数后的规定时间内没有再次触发,才执行。也就是在n秒内无论你触发多少次事件只响应最后一次,如果在规定时间内再次触发,则会重新计算时间。

案例1:

正常情况下每一次点击按钮后都会触发执行

<body>
  <button id="btn">0</button>
  <script>
    let count=0 //记录点击次数
    let btn=document.getElementById("btn") //获取DOM结构
    function add(){
      console.log(count);
      btn.innerHTML=count++ //每点击一次++
    }

    btn.addEventListener('click',add)//给btn绑定监听事件

  </script>
</body>
      

效果:

1681828773062.gif

改成防抖后,只会执行规定时间内最后一次,也就是连续点击多次后之后并不会发送请求,只有在执行规定时间内没有再次触发才执行。

思路: 利用clearTimeout和setTimeout实现

<body>
  <button id="btn">0</button>
  <script src="./debounce.js"></script> //引入防抖js
  <script>
    let count=0  //记录点击次数
    let btn=document.getElementById("btn")  //获取DOM结构

    function add(e){
      // console.log(this);
      console.log(count);
      btn.innerHTML=count++ //每点击一次++
      return 123//希望返回结果
    }
   
    // btn.addEventListener('click',add)
    btn.addEventListener('click',debounce(add,1000))//防抖动 给btn绑定监听事件
    // btn.addEventListener('click',throttle(add,2000))//节流
  </script>
</body>

//debounce.js
function debounce(func,wait){
  let timeout,result
  return function(){
    console.log(this);//this指向btn
    let args=[...arguments]//获取到function中传的所有参数
    clearTimeout(timeout) //每次执行前清空之前的定时器
    timeout= setTimeout(()=>{ //形成了闭包
      result=func.apply(this,args)//此时this和当前函数this相同
    },wait)//定时器会修改this指向 定时器词法环境大多数都是window
    return result //有无返回值取决于add 函数有无返回值
  }

}//一个函数内部的this必然是函数的this

效果:

2.gif

节流(Throttle)

不同于防抖——只有停下来不干才执行,节流就是连续触发的事件每隔规定时间只执行一次

案例2:

思路: 利用时间戳实现。

<body>
  <button id="btn">0</button>
  <script src="./throttle.js"></script>
  <script>
    let count=0 //记录点击次数
    let btn=document.getElementById("btn") //获取DOM结构

    function add(e){
      // console.log(this);
      console.log(count);
      btn.innerHTML=count++ //每点击一次++
      return 123//希望返回结果
    }
   
    // btn.addEventListener('click',add)
    // btn.addEventListener('click',debounce(add,1000))//防抖动
    btn.addEventListener('click',throttle(add,2000))//节流
  </script>
</body>

//引入throttle.js
function throttle(func,wait){
  let preTime=0 //上次时间
  return function(){
    let args=[...arguments] //获取到function中传的所有参数
    let now=+new Date() //时间戳 精准到秒
    if(now-preTime>wait){ //判断现在点击的时间和上一次点击的时间是否在规定wait时间范围内
      func.apply(this,args) 
      preTime=now //更新上一次时间
    }
    
  }
}

效果:

3.gif

防抖和节流

相同点:

  • 都是减少页面上没有必要的操作,一些可能多次手误的操作或手抖导致的没有必要的代码执行。

不同点:

  • 防抖是将连续多次触发直到最后不触发了才执行一次
  • 节流是将连续多次触发变成每隔一段时间执行一次

应用场景

防抖:

  • 搜索框搜索输入。只有用户最后一次输入完,再发送请求
  • 手机号、邮箱验证输入检测

节流:

  • 监听页面的滚动事件
  • 鼠标移动事件

总结

本篇文章就到此为止啦,由于本人经验水平有限,难免会有纰漏,对此欢迎指正。如觉得本文对你有帮助的话,欢迎点赞收藏❤❤❤,您的点赞是持续写作的动力,感谢支持。