防抖和节流函数实现

7/20/2022 js

# 1. 防抖

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

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

// test
let log = debounce(a => console.log(a))
btn.onClick = log(1)

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)
    }

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

# 2. 节流

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

function throttle(fn, hold = 500) {
  let timer = null
  let start = +new Date
  return function (...args) {
    timer && clearTimeout(timer)
    let end = +new Date
    if (end - start >= hold) {
      start = end
      fn.apply(this, args)
    }
    else timer = setTimeout(() => fn.apply(this, args), hold)
  }
}

# 3. 防抖和节流的区别

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

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

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

# 参考

1. 函数防抖与节流 (opens new window)

2. 浅谈js防抖与节流 (opens new window)

    爱自己,
    是终身浪漫的开始。
    红莲华
    x
    loading...