JS面试题---什么是节流和防抖?怎样手写一个自己的节流和防抖工具函数

本文详细介绍了节流和防抖两种技术的概念,手写实现代码示例,以及它们在解决多次点击、搜索联想、滚动事件等场景的应用。重点阐述了两者之间的区别和适用场景,强调了这两种技术在优化性能和提升用户体验中的作用。
摘要由CSDN通过智能技术生成

技术背景:

相信以下场景你都不陌生

  • 多次点击按钮导致页面失去响应或者出现意外情况。
  • 如何实现搜索联想功能以及各企业邮箱提示功能。
  • 页面滚动、输入框输入以及窗口尺寸变化频繁触发事件。
  • 手机号、邮箱格式的实时校验

为了解决或者实现这类场景,优化性能和改善用户体验。衍生出了一种技术,防抖(debouce)和节流(throttle)

一、概念

  • 防抖(debounce)

延迟执行函数,直到一段连续的时间内没有新的事件被触发。

解释:当一个事件在一段时间内连续触发时,只有最后一次触发且经过一定时间后才会执行相应的处理函数
类比:王者荣耀的回城效果,多次点击回城会一直重置回城时间,只有停止点击回城并等待一段时间后才会实现回城功能。

具体来说,当触发一个事件时,防抖函数会启动一个定时器,延迟一段时间执行事件处理函数。如果在这段时间内又触发了同样的事件,就会清除之前的定时器,并重新设置一个新的定时器。只有在最后一个事件触发后,经过一段时间内没有新的事件再次触发时,事件处理函数才会被执行。

  • 节流(throttle)

确保函数在一定时间间隔内最多执行一次,无论事件触发频率如何。

解释:在一段时间内,无论事件触发频率如何,处理函数能且仅能触发一次。
类比:王者荣耀中,在技能的CD周期内,技能仅能触发一次,而且是从第一次触发时开始执行。

具体来说,当触发一个事件时,节流函数会立即执行该事件处理函数,然后在设定的时间间隔内,如果再次触发相同的事件,节流函数会忽略该事件,直到这段时间间隔过去,才会重新触发执行。

二、手写实现

  • 防抖(debounce)
<html>
	<button>打印</button>
	
	<script>
	  /*
	  ******封装防抖工具函数 myDebouce *******
	  */
	  // fn 需要添加防抖效果的函数(回调函数),delay 延迟时间
	  const myDebounce = (fn,delay = 500)=>{
	    // 存储上一次的延时器
	    let timer;
	    return function (...args) {
	      // 清除上一次的延时器
	      clearTimeout(timer);
	      // 重置新的延时器
	      timer =  setTimeout(()=>{
	        fn(...args)
	      },delay)
	    }
	  }
	  // 定义处理函数,并添加防抖效果
	  const click = myDebouce(function(message){
	    console.log(message);
	  },1000)
	  // 绑定点击事件
	  document.querySelector('button').addEventListener('click',function () {
	    click('防抖成功')
	  })
 	</script>
 </html>

如果一直点击按钮,事件不会触发,停止点击delay毫秒后,事件触发

  • 节流(throttle)

方法一: 使用时间戳的写法

<html>
	<button>打印</button>
	
	<script>
	  /*
	  ******封装节流工具函数 throttle*******
	  */
	  // fn 需要添加节流效果的函数(回调函数), T 时间周期,T的默认值是500ms
	  const myThrottle = (fn,T = 500)=>{
	    // 储存上一次函数执行的时间戳
	    let old = 0
	    return function (...args){
	      // 获取当前时间戳
	      const now = new Date().getTime()
	      // 判断当前时间戳与上一次触发的时间戳差值是否大于时间周期
	      if( now - old >= T){
	        fn(...args);
	        // 更新上一次执行的时间戳
	        old = now;
	      }
	    }
	  }
	  // 定义处理函数,并添加节流效果
	  const click = myDebouce(function(message){
	    console.log(message);
	  },1000)
	  // 绑定点击事件
	  document.querySelector('button').addEventListener('click',function () {
	    click('节流成功!按周期,每秒打印一次,无论频率多高')
	  })
 	</script>
 </html>

方法二: 使用定时器 setTimeout 的写法

  // fn 需要添加节流效果的函数(回调函数), T 时间周期
  const myThrottle = (fn,T)=>{
    // 通过闭包保存一个 “节流阀”,默认为false
    let flag = false
    return function (...args){
      // 节流阀存在,表示已经执行
      if(flag){
        return
      }
      else {
        flag = true; //立刻将节流阀设置为true,表示处理函数正在执行
        setTimeout(() => {
          fn(...args)
          //关键!!!! 执行完毕,重置节流阀为false
          flag = false
        }, T);
      }

    }
  }
  // 绑定事件
  const click = myThrottle(function (message) {
    console.log(message)
    },1000)

  // 绑定点击事件
  document.querySelector('button').addEventListener('click',()=>{
    click('节流成功')
  })

如果一直点击按钮,控制台会按T的时间周期一直执行处理函数,在时间周期T内,函数仅能执行一次。

三、使用场景

  • 防抖
  1. 避免用户重复点击按钮等需要网络请求的触发事件。
  2. 搜索框搜索输入,只需用户最后一次输入完,再发送请求。
  3. 调整浏览器窗口resize时,避免重复执行绑定的回调函数,浪费大量资源,降低性能。
  4. 手机号、邮箱号的格式验证。
  • 节流
  1. 滚动加载,加载更多或滚到底部监听。
  2. 搜索框,搜索联想功能
  3. 浏览器播放事件,每个一秒计算一次进度信息等。
  4. 鼠标移动或者滚轮滑动等频繁触发的事件。

四、区别与联系

联系

  1. 都可以通过定时器setTimeout实现
  2. 都是用来限制函数执行频率的技术

区别

  1. 实现方式不同。

函数防抖是在一定时间内,如果事件重复触发,则只执行最后一次操作。函数节流则是在一定时间内,无论事件触发多少次,只会执行一次操作。

  1. 执行时机不同。

函数防抖执行时机在事件停止触发后一段时间后,而函数节流则是在指定时间周期内只会执行一次。

  1. 适用场景不同。

函数防抖适用于一些需要等待用户停止操作之后再执行的场景,如搜索输入框、窗口调整。函数节流适用于一些高频率触发的事件,如鼠标移动事件,滚动事件等。


总而言之,防抖和节流都是用来限制函数执行频率的技术

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值