防抖和节流函数实现

337 阅读2分钟

1. 防抖

防抖(debounce):在第一次触发事件时,不立即执行函数,而是给出一个延迟。若在延迟时间内,不再触发事件那么执行函数;若在延迟时间内再次触发事件,那么以最后一次触发的时机重新计算延迟时间再执行函数。说白了,就是解决用户手抖的情况(#...#)

function debounce(fn, delay = 500) {
  let timer = null
  return function (...args) {
    timer && clearTimeout(timer)
    timer = setTimeout(() => fn.apply(this, ...args), delay)
  }
}

wait!!! 这里防抖虽然是防抖了,但是给用户的感觉是有500ms的延迟,所以我想做个优化,让它第一次就开始执行了,且上次执行完毕后又可以立即执行,即用户手抖开始前立刻执行函数,用户手抖结束后再执行函数,然后继续重复下一轮,总之不能为了面试而面试对吧?

function myDebounce(fn, delay = 500, immediate = 1) {
  // immediate 为立即执行标志,1默认开始立即执行
  let timer = null
  return function (...args) {
    timer && clearTimerout(timer)

    if (immediate) {
      immediate ^= 1 // 众所周知:1^1==0; 0^1==1
      fn.apply(this, args)
      timer = setTimeout(() => immediate ^= 1, delay)
      return
    }

    timer = setTimeout(() => { fn.apply(this, args); immediate ^= 1 }, delay)
  }
}

2. 节流

节流(throttle):如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效

function throttle(fn, hold = 500) {
  let timer = null

  return function (...args) {
    if (timer) return

    fn.apply(this, args)
    timer = setTimeout(() => clearTimeout(timer), hold)
  }
}

3. 防抖和节流的区别

防抖:函数在等待一个delay延迟后再执行

节流:函数在一个hold时间段内只执行一次

简单来说:如果在用户一直点击的情况下:防抖一直都不会触发,直到用户停下来后等待delay延迟才会触发,节流是每隔hold触发一次

参考

1. 函数防抖与节流

2. 浅谈js防抖与节流