JS手写防抖函数

254 阅读1分钟

本项目案例:鼠标移动在div中移动时,页面上的数据对应增加相应的数字

非防抖版本

  • 效果图:

  • 实现代码:
<div id="adder">0</div>
<script>
  const div = document.getElementById('adder')
  // 鼠标移动,加 66
  let num = 66
  // 封装函数
  let divClick = function () {
    div.innerHTML = parseInt(div.innerHTML) + num
  }
  // 监听鼠标移动事件
  div.onmousemove = divClick
</script>

由实现效果可以看到只要鼠标移动就会更新数据,此时更新数据过于频繁,通过防抖限制

防抖-非立即执行版本

由效果图可见,鼠标移动后,鼠标停止1秒后才会增加数据

  • 效果图

  • 实现代码
<div id="adder">0</div>
<script>
  const div = document.getElementById('adder')
  // 封装操作函数,这里可以把num作为参数传入
  let divClick = function (num) {
    div.innerHTML = parseInt(div.innerHTML) + num
  }

  // 封装防抖函数
  function debounce(fn, delay, ...arg) {	// 参数:1.操作函数 2.延迟时间 3.函数参数
    let timer = null				// 定义变量用来存储定时器
    return function () {
      timer && clearTimeout(timer)		// 如果定时器存在,就清空定时器
      // 生成定时器
      timer = setTimeout(() => {		// 此处使用箭头函数,this指向调用防抖函数的对象
        fn.apply(this, arg)			// apply调用函数,传入this与参数数组
      }, delay)
    }
  }

  // 监听鼠标移动事件,调用debounce函数
  div.onmousemove = debounce(divClick,1000,8)	// 1秒内鼠标移动,只增加一次数据,每次加8

防抖-立即执行版本

鼠标一移动就立即执行,之后一直移动都不增加数据,鼠标停止1秒后,再次移动,才会增加数据

  • 效果图

  • 实现代码
<div id="adder">0</div>
<script>
  const div = document.getElementById('adder')
  // 封装函数,这里可以把num作为参数传入
  let divClick = function (num) {
    div.innerHTML = parseInt(div.innerHTML) + num
  }

  // 定义防抖函数
  function debounce(fn, delay, ...arg) {
    let timer = null 						 // 定义变量来存储定时器
    return function () {
      // apply调用函数,传入this 与 参数数组
      timer || fn.apply(this, arg) 		 	 //如果定时器为空,就执行函数
      timer && clearTimeout(timer)  			// 如果定时器存在,就清空定时器
      timer = setTimeout(() => {
        timer = null  				 // delay秒后将定时器设置为空
      }, delay)
    }
  }
  
  // 监听鼠标移动事件,调用debounce函数
  div.onmousemove = debounce(divClick, 1000, 8)	  // 1秒内鼠标移动,只增加一次数据,每次加8
</script>

防抖-合并版本

通过参数控制:是否立即执行

  • 实现代码
<div id="adder">0</div>
<script>
  const div = document.getElementById('adder')
  // 封装函数,这里可以把num作为参数传入
  let divClick = function (num) {
    div.innerHTML = parseInt(div.innerHTML) + num
  }
  
  // 封装防抖函数
  function debounce(fn, delay, isImmediate, ...arg) {
    let timer = null
    return function () {
      timer && clearTimeout(timer)
      // 判断是否需要立即执行
      if (isImmediate) {
        timer || fn.apply(this, arg)
        timer = setTimeout(() => {
          timer = null
        }, delay)
      } else {
        timer = setTimeout(() => {
          fn.apply(this, arg)
        }, delay)
      }
    }
  }

  // 监听鼠标移动事件,调用debounce函数
  	// 1秒内鼠标移动,只增加一次数据,每次加8,不立即执行
  div.onmousemove = debounce(divClick, 1000, false, 8)
</script>