JavaScript实现防抖与节流

javascript,实现,节流 · 浏览次数 : 13

小编点评

**防抖** * 在事件被触发后,等待一段时间后才执行回调函数。 * 如果在这段时间内又触发了该事件,则重新计时。 **节流** * 在一段时间内只允许函数执行一次。 * 如果在这段时间内多次触发该函数,只有某一次触发会执行。 **区别** | 防抖 | 节流 | |---|---| | 等待一段时间后执行 | 仅执行最后一次 | | 允许多次触发 | 仅允许最后一次触发 | | 使用场景 |频繁触发的事件 | 频繁但顺序无关的事件 | **示例** **防抖** ```javascript function debounce(func, delay) { let timeoutId; return function() { clearTimeout(timeoutId); timeoutId = setTimeout(func, delay); } } ``` **节流** ```javascript function throttle(func, delay) { let lastExecTime = 0; return function() { const currentTime = Date.now(); if (currentTime - lastExecTime > delay) { func(); lastExecTime = currentTime; } else { clearTimeout(timeoutId); } } } ``` **使用** 使用防抖可以减少事件回调的执行次数,从而提高性能和减少不必要的资源消耗。使用节流可以控制函数的执行频率,从而提高性能和避免过多的计算或渲染。

正文

1. 引言

有这么一种场景:某个页面表单按钮设置了点击提交事件,有时因为网络不好,点击后后台服务端很久才返回信息,然而用户因等待许久已经多次点击导致多次发送数据,实际上服务器只需要一次发送的数据即可

又比如说这么一种场景:某个页面设置监听的resize事件,一旦resize则重新渲染页面,有时用户会慢慢的拖动导致不断触发resize事件,频繁的触发重新渲染导致页面出现问题,实际上只需要在一段时间内执行最后一次resize事件的重新渲染即可

解决诸如上述场景的问题,可以使用防抖节流

防抖(Debounce)和节流(Throttle)是两种常用的优化JavaScript性能的技术

2. 防抖

防抖是指在事件被触发后,等待一段时间后才执行回调函数。如果在这段时间内又触发了该事件,则重新计时。防抖常用于处理频繁触发的事件,如窗口大小调整、搜索框输入等。通过防抖可以减少事件回调的执行次数,从而提高性能和减少不必要的资源消耗

示例代码如下:

function debounce(func, delay) {
  let timeoutId;

  return function() {
    clearTimeout(timeoutId);

    timeoutId = setTimeout(func, delay);
  }
}

function handleResize() {
  // 处理窗口大小调整的逻辑
}

window.addEventListener('resize', debounce(handleResize, 200));

防抖较为简单,就是等待一段时间后执行

3. 节流

节流是指在一段时间内只允许函数执行一次。如果在这段时间内多次触发该函数,只有某一次触发会执行,其余触发会被忽略。节流常用于处理高频率触发的事件,如滚动事件、鼠标移动事件等。通过节流可以控制函数的执行频率,从而提高性能和避免过多的计算或渲染

示例代码如下:

function throttle(func, delay) {
  let lastExecTime = 0;

  return function() {
    const currentTime = Date.now();

    if (currentTime - lastExecTime > delay) {
      func();
      lastExecTime = currentTime;
    } 
  }
}

function handleScroll() {
  // 处理滚动事件的逻辑
}

window.addEventListener('scroll', throttle(handleScroll, 200));

测试如下,未设置节流时,下图页面滑动触发11次scroll处理函数,设置节流后触发3次scroll处理函数:

未设置节流window.addEventListener('scroll', handleScroll)

image-20230725144058251

设置节流window.addEventListener('scroll', throttle(handleScroll, 200))

image-20230725144009779

上述节流代码设置为只执行一段时间内的第一次,节流也可以设置为只执行最后一次,示例代码如下:

    function throttle(func, delay) {
      let timeoutId;
      let lastExecTime = 0;

      return function () {
        const currentTime = Date.now();

        if (currentTime - lastExecTime > delay) {
          func();
          lastExecTime = currentTime;
        } else {
          clearTimeout(timeoutId);

          timeoutId = setTimeout(function () {
            func();
            lastExecTime = currentTime;
          }, delay-(currentTime - lastExecTime));
        }
      }
    }

    function handleScroll() {
      // 处理滚动事件的逻辑
      console.log('scroll');
    }

    window.addEventListener('scroll', throttle(handleScroll, 200));

4. 区别

防抖是等待一段时间后执行,且只执行最后一次

节流是一段时间内只执行一次,执行第一次或最后一次都行

5. 第三方库

Lodash 是一个 JavaScript 实用工具库,包含了防抖和节流函数

修改防抖部分代码:

<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
<script>
    function handleResize() {
        // 处理窗口大小调整的逻辑
        console.log('resize');
    }

    window.addEventListener('resize', _.debounce(handleResize, 200));
</script>

修改节流部分代码:

<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
<script>
    function handleScroll() {
        // 处理滚动事件的逻辑
        console.log('scroll');
    }

    window.addEventListener('scroll', _.throttle(handleScroll, 200, { trailing: false })); 
    // trailing: false 表示禁用最后一次执行,即执行第一次
</script>

更为具体的函数API解释可查看文档:

6. 参考资料

[1] 前端性能优化篇: 防抖和节流 - 掘金 (juejin.cn)

[2] lodash.debounce | Lodash中文文档 | Lodash中文网 (lodashjs.com)

[3] lodash.throttle | Lodash中文文档 | Lodash中文网 (lodashjs.com)

与JavaScript实现防抖与节流相似的内容:

JavaScript实现防抖与节流

防抖(Debounce)和节流(Throttle)是两种常用的优化JavaScript性能的技术

如何使用JavaScript实现在线Excel附件的上传与下载?

前言 在本地使用Excel时,经常会有需要在Excel中添加一些附件文件的需求,例如在Excel中附带一些Word,CAD图等等。同样的,类比到Web端,现在很多人用的在线Excel是否也可以像本地一样实现附件文件的操作呢?答案是肯定的,不过和本地不同的是,Web端不会直接打开附件,而是使用超链接单

第120篇: DOM编程(常用操作、动态脚本、样式及动态表格)

好家伙,我回来了, 本篇为《JS高级程序设计》第十四章“DOM编程”学习笔记 1.DOM编程 我们知道DOM是HTML文档的编程接口, 我们可以通过HTML代码实现DOM操作, 也同样能够通过JavaScript实现DOM操作。 2.JS操作DOM 我们来简单的举个例子: 随便开一个空白的html页

JavaScript 如何实现一个响应式系统

JavaScript 如何实现一个响应式系统 第一阶段目标 数据变化重新运行依赖数据的过程 第一阶段问题 如何知道数据发生了变化 如何知道哪些过程依赖了哪些数据 第一阶段问题的解决方案 我们可用参考现有的响应式系统(vue) vue2 是通过 Object.defineProperty实现数据变化的

JavaScript能否实现在线Excel附件的上传与下载?

>摘要:本文由葡萄城技术团队于博客园原创并首发。转载请注明出处:[葡萄城官网](https://www.grapecity.com.cn/),葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 # 前言 在本地使用Excel时,经常会有需要在Excel中添加一些附件文件的需求,例如在Ex

第一百一十五篇: JS集合引用类型Map

好家伙,本篇为《JS高级程序设计》第六章“集合引用类型”学习笔记 1.Map ECMAScript6以前,在JavaScript中实现“键/值”式存储可以使用object来方便高效地完成,也就是使用对象属性作为键,再使用属性来引用值。 但这种实现并非没有问题,为此TC39委员会专门为“键/值”存储定

如何移除事件监听器

在运行时清理你的代码是构建高效、可预测的应用程序,没有商量余地的部分。在JavaScript中,实现这一目标的方法之一是很好地管理事件监听器,尤其是当不再需要时移除它们。 有好几种方法可以做到这件事情,每种都有自己的一套权衡方法,使其在某些情况下更合适。我们将介绍几种最常用的策略,以及当你试图决定哪

JavaScript系列:JS实现复制粘贴文字以及图片

目录一. 基于 Clipboard API 复制文字(推荐)基本概念主要方法使用限制实际应用示例二、基于 document.execCommand('copy')缺陷实际应用示例说明三、复制图片功能四、封装 一. 基于 Clipboard API 复制文字(推荐) 基本概念 Clipboard AP

JavaScript利用反射实现方法注入

利用反射来实现对JavaScript对象的方法注入,主要使用Reflect和Object.getOwnPropertyDescriptor()来实现

JavaScript 如何验证 URL

前言 当开发者需要为不同目的以不同形式处理URL时,比如说浏览器历史导航,锚点目标,查询参数等等,我们经常会借助于JavaScript。然而,它的频繁使用促使攻击者利用其漏洞。这种被利用的风险是我们必须在我们的JavaScript应用程序中实现URL验证的原因。 URL验证检查URL是否遵循正确的U