这一次彻底弄懂函数防抖与函数节流

1,016 阅读3分钟

函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段。

779d68c36e7e4125a362c4834665eb69_tplv-k3u1fbpfcp-watermark.webp

我们了解一下什么是防抖

函数防抖: 频繁触发的情况下,只有等待足够的空闲时间,才可以执行代码一次。

函数防抖的影响:防止函数在极短的时间内反复调用,造成资源的浪费。

就比如在页面上的某些事件触发频率非常高,比如滚动条滚动、窗口尺寸变化、鼠标移动等,如果我们需要注册这类事件,不得不考虑效率问题,又特别是事件处理中涉及到了大量的操作,让我们为之头痛。 当窗口尺寸发生变化时,哪怕只变化了一点点,都有可能造成成百上千次对处理函数的调用, 这对网页性能的影响是极其巨大的,很可能就造成页面的阻塞。于是,我们可以考虑,每次窗口尺寸变化、滚动条滚动、鼠标移动,不要立即执行相关操作,而是等一段时间,以窗口尺寸停止变化、滚动条不再滚动、鼠标不再移动为计时起点,一段时间后再去执行操作,就像电梯关门那样。

也就是说触发高频事件 N 秒后只会执行一次,如果 N 秒内事件再次触发,则会重新计时,重新开始计时。

// 简单版本
function debounce(func, wait) {
// 使用闭包来维护timer
    var timeout = null; 
   
    return function () {
        var context = this;
        var args = arguments;
        clearTimeout(timeout) 
        // 注册回调函数
        timeout = setTimeout(function(){
            func.apply(context, args)
        }, wait);
    }
}
function testout(e, content) {
    console.log(e, content);
}
var fn = debounce(testout, 2000); // 防抖函数
document.onmousemove = function (e) {
   fn(e, 'debounce'); // 给防抖函数传参
}

鼠标一直移动(一直在触发onmousemove里面的事件,但是有debounce约束),则不输出,若停止移动,则在间隔1S后输出一次(唯一的一次哦!!!))

setInterval(debounce(fn,500),1000) // 第一次在1500ms后触发打印,之后每1000ms触发一次
打印一次debounce
setInterval(debounce(fn,2000),1000) // 不会触发一次(我把函数防抖看出技能读条,如果读条没完成就用技能,便会失败而且重新读条)

应用场景有表单的防止重复提交,搜索框提示发送多次HTTP请求 有兴趣的可以输入的了解一下哦!

参考JavaScript专题之跟着underscore学防抖

什么是节流

节流函数: 让一个函数无法在短时间内连续调用,只有当上一次函数执行后,过了规定的时间间隔,才能进行下一次该函数的调用。或者说你在操作的时候不会马上执行该函数,而是等你不操作的时候才会执行。 对于函数节流,有如下几个场景:

1. 游戏中的刷新率
2. DOM元素拖拽
3. Canvas画笔功能

函数节流

function throttle(fn, gapTime) {
  let _lastTime = null;

  return function () {
    let _nowTime = + new Date()
    if (_nowTime - _lastTime > gapTime || !_lastTime) {
      fn();
      _lastTime = _nowTime
    }
  }
}

let fn = ()=>{
  console.log('boom')
}

setInterval(throttle(fn,1000),100)

每0.1s在任务队列中注册一个throttle函数,实现的一个简单的函数节流,结果却是一秒打出一次boom

小结::函数防抖和节流,都是控制事件触发频率的方法。

参考阅读

juejin.cn/post/684490…