函数节流(throttle)与函数去抖(debounce)

一、 引申

  在项目中总会碰到一些因为事件频繁触发,导致 DOM 操作、资源加载等严重消耗资源行为。

  1. window对象的resize、scroll事件

  2. 拖拽时的mousemove事件

  3. 射击游戏中的mousedown、keydown事件

  4. 文字输入、自动完成的keyup事件

  针对这些事件就出现了debounce和throttle两种解决办法。

二、函数节流(throttle)

规定在一个时间间隔内,只能触发一次函数。即使这个时间间隔内触发多次函数,也只有一次生效。

throttle (fn, interval){
  let last = 0
  return function() {
    let cur = Date.now()
    if (cur - last > interval) {
      fn.apply(this, arguments)
      last = cur
    }
  }
}

 三、 函数去抖(debounce)

// 思路:在规定时间内未触发第二次,则执行,即在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

在《JavaScript高级程序设计》一书有介绍函数去抖,里面封装了这样一个函数去抖函数:

function throttle(method, context) {
     clearTimeout(methor.tId);
     method.tId = setTimeout(function(){
         method.call(context);
     }, 1000);
 }

它把定时器ID存为函数的一个属性。并且没有触发1s调用一次,而调用的时候就直接写

window.onresize = function(){
    throttle(myFunc);
}

它就是利用为函数添加属性的方式增加定时器,但是可能会被修改,下面是我自己封装的一个使用闭包的去抖函数。高内聚低耦合

 function debounce (fn, delay) {
  let lastFn = null
 // 利用闭包保存定时器 return function() { let args = arguments
  // 在规定时间内再次出发会先清除定时器后再重设定时器 clearTimeout(lastFunc) lastFn = setTimeout(() => { fn.apply(this, args) }, delay) } }
function fn () {
  console.log('防抖')
}

let debounceFn = debounce(fn, 1000) // 重要,需要将去抖函数指向内存中闭包位置

某DOM.addEventListener('scroll', function () { // 也可以改为其他任意方法
  debounceFn()
}) 

 

总结

  • 函数去抖和函数节流都是防止某一时间频繁触发,但是这两兄弟之间的原理却不一样。
  • 函数去抖是某一段时间内只执行一次,而函数节流是间隔时间执行。
posted @ 2019-08-05 08:29  爱看星星的稻草人  阅读(258)  评论(0编辑  收藏  举报