【JS基础】 函数防抖和节流

158 阅读1分钟

防抖(debounce)

概念

在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

怎么理解这句话,有网友这样比喻:
LOL英雄有些技能发动前要读条(比如1s),如果这1s内又按下技能键,就要重新读条

实现

function debounce(fn, wait = 1000, immediate) {
  let timerId = null
  function debounced(...args) {
    if (timerId) clearTimeout(timerId)
    if (immediate) {
      // timerId为空时,立即执行
      let isCallNow = !timerId
      // 开始延时
      timerId = setTimeout(() => {
        timerId = null
      }, wait)
      if (isCallNow) fn.apply(this, args)
    } else {
      timerId = setTimeout(() => {
        fn.apply(this, args)
      }, wait)
    }
  }
  return debounced
}

验证:

<script>
    const debounceOk = debounce(() => {
      handleOk()
    }, 1000, true)
    function handleOk() {
      console.log('ok')
    }
</script>
<div>
    <button onclick="debounceOk()">确定</button>
</div>

节流(throttle)

概念

规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。 还是以LOL为例: 当前英雄的攻速为1.0, 那1s内就能一次平a。

实现

function throttle(fn, wait = 2000) {
  let prev = Date.now()
  function throttled(...args) {
    let now = Date.now()
    if (now - prev > wait) {
      fn.apply(this, args)
      prev = Date.now()
    }
  }
  return throttled
}

验证:

<script>
    const throttleOk = throttle(() => {
      handleOk()
    }, 1000)
    function handleOk() {
      console.log('ok', Date.now())
    }
</script>
<div>
    <button onclick="throttleOk()">确定</button>
</div>