# 防抖和节流

debounce 是防抖策略,throttle 是节流,两者的区别在于:throttle 确保一段时间内只执行一次,而 debounce 是防抖,要连续操作结束后再执行。以网页滚动为例,debounce 要等到用户停止滚动后才执行,throttle 则是如果用户一直在滚动网页,那么在滚动过程中还是会执行。

# 防抖

/*
@params:
  func[function]:最后要触发执行的函数
  wait[number]:频繁设定的界限
  immediate[boolean]:默认多次操作,我们识别的是最后一次,但是immediate=true,让其识别第一次
@return
  可以被调用执行的函数
 */
function debounce(func, wait = 300, immediate = false) {
  let timer = null
  return function anonymous(...params) {
    let now = immediate && !timer

    //每次点击都把之前设置的定时器清除掉
    clearTimeout(timer)
    //重新设置一个新的定时器监听wait事件内是否触发第二次
    timer = setTimeout(() => {
      timer = null //垃圾回收机制
      //wait这么久的等待中,没有触发第二次
      !immediate ? func.call(this, ...params) : null
    }, wait)

    //如果是立即执行
    now ? func.call(this, ...params) : null
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 节流

/*
@params:
    func[function]:最后要触发执行的函数
    interval[number]:触发的时间间隔 默认300ms内执行一次
  @return
    可以被调用执行的函数
*/

function throttle(func, interval) {
  var timer = null,
    last = null //记录上一次执行时间
  return function(...args) {
    let now = new Date() //记录当前时间
    if (last && now - last < interval) {
      //两次操作的间隔时间还不符合触发的频率
      clearTimeout(timer)
      timer = setTimeout(() => {
        last = now
        func.call(this, ...args)
      }, interval)
    } else {
      //两次操作的间隔时间已经超过wait了,可以立即执行了
      last = now
      func.call(this, ...args)
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27