手写防抖和节流

95 阅读3分钟

防抖(debounce)

防抖 : 在单位时间内 , 频繁触发事件 , 只执行最后一次

比如 : 王者荣耀回城 , 只要被打断 , 回城的进度条就需要重新开始加载

使用场景 :

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

例如,当我们在搜索框中输入关键词时,输入框会不断触发 oninput 事件,如果每次输入都去请求服务器获取数据,会造成不必要的请求浪费。此时就可以使用防抖技术,将一定时间内的多次触发合并为一次操作,只请求一次服务器数据,减少了请求次数和服务器负载。

节流(throttle)

节流 : 在单位时间内 , 频繁的触发事件 , 只执行一次

节流也叫节流阀

比如 : 王者荣耀技能冷却时间 , 期间无法继续释放技能

使用场景 :

  • 高频事件 : 鼠标移动 mousemove , 页面尺寸缩放 resize , 滚动条滚动 scroll 等等

例如,当我们拖动网页上的滚动条时,会不断触发 onscroll 事件,如果每次触发都去计算滚动距离,会造成浏览器性能下降。此时就可以使用节流技术,将一定时间内的多次触发限制为一次操作,只计算一次滚动距离,提高了浏览器性能和用户体验。

示例代码

根据监听页面的缩放( resize )来完成防抖和节流

定义一个函数作为要传的参数

    // 定义一个函数作为要传的参数
    function content(e) {
        console.log('嘎嘎嘎',e);
    }
节流
   // 监听页面的resize事件, 调用 throttle 节流函数
   window.addEventListener('resize',throttle(content,20))
   // 节流
   function throttle(fn,n){
   // 定义一个变量
       let timeId
       // 返回一个函数
      // arguments : arguments 对象包含了函数被调用时传递的所有参数,不论是否在函数定义中声明
      // 这意味着即使你没有在函数参数中明确声明参数,你仍然可以通过 arguments 对象来访问它们。
       return function (...arguments){
       // 判断如果没有 timeId 时 , 赋一个定时器
           if(!timeId){
            // 调用外层函数 timeId 变量(闭包)
               timeId=setTimeout(()=>{
                   fn.apply(this,arguments)
                   // 在函数执行完后,将 timeId 设置为 null ,表示定时器已经执行完成。
                   timeId=null
               },n)
           }
       }
   }
防抖
   // 监听页面的resize事件, 调用 debounce 防抖函数
    window.addEventListener('resize',debounce(content,200))
    // 防抖
    function debounce(fn,n){
    // 定义一个变量
       let timeId
   // 返回一个函数
   // arguments : arguments 对象包含了函数被调用时传递的所有参数,不论是否在函数定义中声明
   // 这意味着即使你没有在函数参数中明确声明参数,你仍然可以通过 arguments 对象来访问它们。
       return function(...arguments){
       // 清空定时器
        clearTimeout(timeId)
        // 调用外层函数 timeId 变量(闭包)
        timeId=setTimeout(()=>{
        // 调用参数函数 , apply 是用来动态改变 this 的指向
            fn.apply(this,arguments)
        },n)
       }
    }