防抖和节流

Debounce

  • 每次触发函数,都将原来的定时器清空
  • 一直触发函数,那定时器就一直在被清空,
  • 直到下一次触发函数间隔超过了延迟时间, 回调函数才会被执行
    这是防抖的原理
function debounce(fun, delay, immediate){
  var timeout = null, 
      result = null
  return function(){
    var _this = this
    var args = arguments
    // 在 setTimeOut 中, this 指向 window,
    // func 原有的 this 以及 arguments 会丢失
    // 所以在这里保存下来,使用 apply(call),将这个保存下来的参数传递进去
    timeout ? clearTimeout(timeout) : ''
    // 希望事件触发之后,先立即执行一次,
    // 下一次执行才延迟
    if(immediate){
      // 如果在一次事件触发过程中,定时器的回调函数被执行过
      // timeout 就是有值的,而不是 null
      // 所以 !null == true 的时候,就是回调函数函数可以运行的时候(canRun)
      var canRun = !timeout
      timeout = setTimeout(function(){
        timeout = null
      }, delay)
      canRun ? result = fun.apply(_this, args) : ''
    }else{
      timeout = setTimeout(function(){
        fun.call(_this, args)
      }, delay)
    }
    return result
  }
}

这几行代码重点解释一下:

timeout = setTimeout(function(){
  timeout = null
}, delay)

希望每次都是在间隔结束后立即触发函数,而不是等延迟结束再触发。这么说可能有点绕,设想: 延迟时间为10s,第一次触发需要debounce的事件,然后停止事件的触发操作;等待10s,回调函数执行。
第二次触发,在等待10s,回调函数执行。这就是else代码块里面的逻辑。

然后上面的代码是: 如果timeoutnull,就让其立即执行,但是执行之后,要将timeout置为null,否则下次就会得到canRun的值为false,不会触发回调函数。

Throttle

节流就是对于频繁触发的事件,在一段时间内只触发一次。

function throttle(fun, delay){
  var prev = 0
  return function(){
    var now = +new Date()
    var _this = this
    var args = arguments
    if(now - prev > delay){
      fun.apply(_this, args)
      prev = now
    }
  }
}
function throttle(fun, delay){
  var timeout = null
  return function(){
    var _this = this
    var args = arguments
    if(!timeout){
      timeout = setTimeout(function(){
        timeout = null
        fun.apply(_this, args)
      }, delay)
    }
  }
}

区别

防抖:当你患有癫痫的手一顿操作使其事件一直触发,某个时候停了,并且停顿的时间超过延迟时间之后,执行一次函数。
节流:当你患有癫痫的手一直触发某个操作,但是能让函数在一段时间内只触发一次。

你可能感兴趣的:(防抖和节流)