关于去抖和节流

前言

关于移动端的scroll的优化,还有轮播图的实现是面试中经常考察的问题,顺带就会涉及到节流和去抖的原理,说不定柯里化呀,来实现个bind呀,什么的。。用ES6实现呀~balabala就出现了。。今天终于搞懂了这两货是怎么回事,遂来总结一下啦!第一次听到他俩是去年吧 囧。。

去抖(debounce)

debounce的效果是:为了避免函数频繁执行,我们设定一个delay,如果本次执行距离上一次的时间少于delay那么我们不会执行他。
他和节流很大一个区别就是如果你不停的去触发一个去抖过的函数,那么它永远也不会执行。
那么它适合那些场景呢?
每次 resize/scroll 触发统计事件
文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)
简而言之,停下来才会触发的事情啦~。
懒加载如果用去抖,只有停下来才会触发我们的监听事件(所以应该用节流)

去抖的实现:

 function debounce(func, delay) {
  return function(args) {
    var _this = this
    var _args = args
    clearTimeout(func.id)
    func.id = setTimeout(function() {
      func.call(_this, _args)
    }, delay)
 }
}

去抖的实现很容易,每次触发函数时,clearTimeout就好,如果你太快,那之前的timeout就没咯~

节流(throttle)

节流也需要运用到setTimeout,他和去抖的区别是,如果你频繁的触发事件,事件会按照你指定的delay来触发。就想BIUBIUBIUBIUBIU。。。。会节流成 BIU BIU BIU。。。。。不停的触发,函数会按照你指定的频率来执行。不会像debounce那样,就不执行了。
他适合的场景就比较多了,高频转低频的场景都很棒:
DOM 元素的拖拽功能实现(mousemove)
射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
计算鼠标移动的距离(mousemove)
Canvas 模拟画板功能(mousemove)
搜索联想(keyup)
监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次

实现如下:

  function throttle(func, delay) {
  var last, deferTimer
  return function() {
    var _this = this
    var _args = arguments
    var now = +new Date()
    if(last && now < last + delay) {
    //如果 now - last < 我们的delay。我们取消掉他
      clearTimeout(deferTimer)
      deferTimer = setTimeout(function() {
        last = now
        func.apply(_this, _args)
      }, delay)
    }else {
      //如果now - last > delay,我们立即执行他
      last = now
      func.apply(_this, _args)
    }
  }
  //这个if else的结果就是,反复执行的时候会不停的进行时间判断
  //如果now - last > delay也就是间隔大于了delay我们会触发他。
  //这就避免了debounce永远不执行的命运。。当然只有间隔大于delay
  //的时候。    当间隔小于delay , now - last < delay,我们用类似于debounce的方式过滤掉间隔小于delay的触发。
}

结语

= =。话不多说。希望能有面试哇!!Orz