了解防抖debounce函数与节流throttle函数

作用

  • 优化高频率执行js代码的一种手段,js中的一些事件如浏览器的resize、scroll,鼠标的mousemove、mouseover,input输入框的keypress等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能。
  • 为了优化体验,需要对这类事件进行调用次数的限制

防抖函数

在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

对于函数防抖,有以下几种应用场景:

  • 给按钮加函数防抖防止表单多次提交。
  • 对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。
  • 判断scroll是否滑到底部,滚动事件+函数防抖

总的来说,适合多次事件一次响应的情况

  • 首先我们写一个监听鼠标移动事件:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    function testDebounce() {
     
     
        console.log('test');
    }
    document.onmousemove = () => {
     
     
      testDebounce();
    }
  </script>
</body>
</html>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MCQvkJaf-1613098911872)(/Users/mac/Desktop/前端学习笔记/Javascript/JS高级/防抖函数与节流函数/1.gif)]

  • 最简单的防抖函数:
var timer; // 维护同一个timer
function debounce(fn, delay) {
    
    
    clearTimeout(timer);
    timer = setTimeout(function(){
    
    
        fn();
    }, delay);
}
  • 为鼠标移动事件添加防抖函数:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    var timer; // 维护同一个timer
    function debounce(fn, delay) {
     
     
        clearTimeout(timer);
        timer = setTimeout(function(){
     
     
            fn();
        }, delay);
    }
    // test
    function testDebounce() {
     
     
        console.log('test');
    }
    document.onmousemove = () => {
     
     
      // testDebounce();
      debounce(testDebounce, 1000);
    }
  </script>
</body>
</html>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YhIeNb8m-1613098911875)(/Users/mac/Desktop/前端学习笔记/Javascript/JS高级/防抖函数与节流函数/2.gif)]

  • 上面例子中的debounce就是防抖函数,在document中鼠标移动的时候,会在onmousemove最后触发的1s后执行回调函数testDebounce;如果我们一直在浏览器中移动鼠标(比如10s),会发现会在10 + 1s后才会执行testDebounce函数(因为clearTimeout(timer)),这个就是函数防抖。

  • 可以看到大大减小了onmousemove事件的调用次数。

  • 防抖函数优化进阶:

function debounce(fn, delay) {
    
    
  let timer = null;
  return function(...args) {
    
    
    if(timer) clearTimeout(timer);
    timer = setTimeout(() => {
    
    
  	  fn.apply(this, args);
    }, delay);
  }
}
  • 进阶测试:
function debounce(fn, delay) {
    
    
  let timer = null;
  return function(...args) {
    
    
    if(timer) clearTimeout(timer);
    timer = setTimeout(() => {
    
    
      fn.apply(this, args);
    }, delay);
  }
}
// test
function testDebounce(e, content) {
    
    
  console.log(e, content);
}
var testDebounceFn = debounce(testDebounce, 1000); // 防抖函数
document.onmousemove = function (e) {
    
    
  testDebounceFn(e, 'debounce'); // 给防抖函数传参
}

节流函数

每隔一段时间,只执行一次函数。

对于函数节流,有如下几个场景:

  • 游戏中的刷新率
  • DOM元素拖拽
  • 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),10)

结果是一秒打出一次boom

比较

相同点:

  • 都可以通过使用 setTimeout 实现。
  • 目的都是,降低回调执行频率。节省计算资源。

不同点:

  • 函数防抖,在一段连续操作结束后,处理回调,利用clearTimeout 和 setTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。
  • 函数防抖关注一定时间连续触发的事件只在最后执行一次,而函数节流侧重于一段时间内只执行一次。

猜你喜欢

转载自blog.csdn.net/weixin_46351593/article/details/113793987
今日推荐