js防抖节流详解

462 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天

防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。

防抖函数的作用就是控制函数在一定时间内的执行次数。防抖意味着 N 秒内函数只会被执行一次(最后一次),如果 N 秒内再次被触发,则重新计算延迟时间。

节流函数的作用是规定一个单位时间,在这个单位时间内最多只能触发一次函数执行,如果这个单位时间内多次触发函数,只能有一次生效。

编写代码的核心思路:

定时器(控制)==>变量,变量(控制)==>目标函数。


简言之:就是通过定时器控制一个变量(比如timer),变量去控制目标函数是否可执行,

如果过了指定时间,那么目标函数就可以执行。比如防抖函数就是,如果在指定时间内又执行了一次,那么重置定时器的时间,当指定时间过了,才通过设置变量才能去执行目标函数。

而节流函数就是,和防抖函数相比就是少了重置定时器那个步骤,其他基本一样。声明一个变量,判断变量是否可以执行目标函数,设置一个定时器控制变量,过了指定时间后,变量通过定时器设置为可以执行目标函数。

防抖函数

//整体逻辑就是,首先设置timer为null,为了首次执行fn,然后设置定时器(timer为真),
//如果没有经过等待时间wait又执行了一次,那么timer还没被设置为null,这时函数无法执行,
//并且重置设置,等待时间wait被刷新
//定时器timer会被清理
function debounce(fn, wait) {
  let timer = null
  return function () {   
    const args = arguments
    const now = !timer            //这里如果timer为真,目标函数fn则无法执行
    timer && clearTimeout(timer)  //如果timer为真,timer会被清理掉
    timer = setTimeout(() => {    //重新设置timer
      timer = null              //定时器过了wait时间后才能设置timer为null,
    }, wait)											//然后目标函数fn才能执行
    if (now) {
      fn.apply(this, args)
    }
  }
}

使用方式

<button onclick="testDebounce()">防抖点击</button>

function avoidClick(){
  console.log("debounce");
}

let testDebounce=debounce(avoidClick,1000)

节流

function throttle(fn,wait){   //定时器版本
  let timer=null;
  return function(){
    let that=this;
    let args=arguments;
    if(!timer){
      timer=setTimeout(()=>{
        timer=null;
      },wait)
      fn.apply(that,args)
    }
  }
}

使用方式

<div onmousemove="testThrottle()"></div> 

function mousemove(event){
  let e=event||window.event
  console.log("鼠标坐标",e.offsetX,e.offsetY);
}
let testThrottle=throttle(mousemove,500)