JavaScript 中的防抖和节流,它们的区别是什么,以及如何实现?

news2025/2/12 1:37:14

在前端开发中,防抖(Debounce)节流(Throttle)是两种常用的优化高频率事件处理的技术。

它们能够有效减少事件处理函数的执行次数,从而提升页面性能和用户体验。

下面将详细解释这两种技术的概念、区别、实现方法以及在日常开发中的使用建议和注意事项。

一、防抖(Debounce)

概念:防抖是指在事件被触发后,等待一定的时间,如果在这段时间内没有再次触发该事件,则执行一次事件处理函数;如果在等待期间内事件再次被触发,则重新计时。

应用场景

  • 窗口调整大小(resize):用户调整窗口大小时,频繁触发resize事件,使用防抖可以只在用户停止调整后执行一次处理逻辑。
  • 输入框实时搜索:用户在输入框中输入内容时,频繁触发输入事件,使用防抖可以只在用户停止输入一段时间后才发送搜索请求。

实现

/**
 * 防抖函数
 * @param {Function} func - 需要防抖处理的函数
 * @param {number} wait - 等待时间(毫秒)
 * @param {boolean} immediate - 是否立即执行
 * @returns {Function} - 返回防抖处理后的函数
 */
function debounce(func, wait, immediate = false) {
    let timeout; // 定义一个定时器变量

    return function(...args) {
        const context = this; // 保存当前上下文

        const later = () => {
            timeout = null; // 清空定时器
            if (!immediate) func.apply(context, args); // 如果不是立即执行,则执行函数
        };

        const callNow = immediate && !timeout; // 判断是否立即执行

        clearTimeout(timeout); // 清除之前的定时器
        timeout = setTimeout(later, wait); // 设置新的定时器

        if (callNow) func.apply(context, args); // 如果需要立即执行,则执行函数
    };
}

// 使用示例
const handleResize = debounce(() => {
    console.log('窗口大小调整完成');
}, 300);

window.addEventListener('resize', handleResize);

代码说明

  • debounce 函数接收一个函数 func、等待时间 wait 和一个布尔值 immediate
  • 返回一个新的函数,在该函数被调用时,会设置一个定时器 timeout,在 wait 时间后执行 func
  • 如果在 wait 时间内再次调用该函数,会清除之前的定时器并重新设置,从而实现防抖效果。
  • 参数 immediate 控制是否在第一次触发时立即执行函数。
二、节流(Throttle)

概念:节流是指在一定的时间间隔内,只执行一次事件处理函数。无论事件触发频率多高,处理函数都会按照固定的时间间隔执行。

应用场景

  • 滚动事件(scroll):用户滚动页面时,频繁触发scroll事件,使用节流可以限制处理函数的执行频率,提升性能。
  • 鼠标移动事件(mousemove):在拖拽操作中,频繁触发mousemove事件,使用节流可以减少处理次数。

实现

/**
 * 节流函数
 * @param {Function} func - 需要节流处理的函数
 * @param {number} wait - 时间间隔(毫秒)
 * @param {Object} options - 可选参数
 * @param {boolean} options.leading - 是否在开始时执行
 * @param {boolean} options.trailing - 是否在结束时执行
 * @returns {Function} - 返回节流处理后的函数
 */
function throttle(func, wait, options = {}) {
    let timeout = null; // 定时器变量
    let lastArgs = null; // 上一次的参数
    let lastThis = null; // 上一次的上下文
    let lastCallTime = 0; // 上一次调用的时间

    const later = () => {
        lastCallTime = options.leading === false ? 0 : Date.now();
        timeout = null;
        func.apply(lastThis, lastArgs);
        if (!timeout) lastArgs = lastThis = null;
    };

    return function(...args) {
        const now = Date.now();
        if (!lastCallTime && options.leading === false) lastCallTime = now;
        const remaining = wait - (now - lastCallTime);

        lastArgs = args;
        lastThis = this;

        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            lastCallTime = now;
            func.apply(lastThis, lastArgs);
        } else if (!timeout && options.trailing !== false) {
            timeout = setTimeout(later, remaining);
        }
    };
}

// 使用示例
const handleScroll = throttle(() => {
    console.log('页面滚动');
}, 200);

window.addEventListener('scroll', handleScroll);

代码说明

  • throttle 函数接收一个函数 func、时间间隔 wait 和一个可选参数对象 options
  • 返回一个新的函数,在该函数被调用时,会根据时间间隔 wait 来决定是否执行 func
  • 参数 options.leading 控制是否在开始时立即执行,options.trailing 控制是否在结束时执行。
  • 通过记录上一次调用的时间和设置定时器,实现节流效果。
三、防抖与节流的区别
特性防抖(Debounce)节流(Throttle)
执行时机在事件停止触发后的一段时间内执行一次在固定的时间间隔内执行一次
适用场景输入框实时搜索、窗口调整大小等需要等待用户停止操作的场景滚动事件、鼠标移动事件等需要限制执行频率的场景
实现方式通过不断重置定时器,确保只有在最后一次触发后的一段时间内没有新的触发才执行通过记录上次执行时间,控制函数的执行频率
四、日常开发中的使用建议
  1. 合理选择防抖和节流

    • 对于需要等待用户停止操作的事件(如输入、窗口调整),使用防抖更为合适。
    • 对于需要限制执行频率的事件(如滚动、拖拽),使用节流更为合适。
  2. 优化用户体验

    • 在高频率触发的事件中,合理使用防抖和节流,可以避免因频繁执行导致的页面卡顿或性能问题。
    • 例如,在搜索框中输入内容时,使用防抖可以减少不必要的搜索请求,提高响应速度。
  3. 结合实际需求调整参数

    • 根据具体业务场景,调整防抖和节流的等待时间或时间间隔,以达到最佳效果。
    • 例如,对于快速滚动的页面,可以将节流的时间间隔设置为100ms,以平衡性能和响应速度。
五、实际开发过程中需要注意的点
  1. 内存管理

    • 确保在组件销毁或不再需要监听事件时,移除相应的事件监听器,防止内存泄漏。
    • 例如,使用 removeEventListener 移除绑定的防抖或节流函数。
  2. 函数上下文和参数传递

    • 在实现防抖和节流时,注意保持原函数的上下文 (this) 和参数,确保函数执行时的正确性。
    • 例如,使用 func.apply(this, args) 来调用原函数。
  3. 兼容性和性能

    • 在不同浏览器和设备上测试防抖和节流的效果,确保兼容性。
    • 避免在节流或防抖函数中执行过于复杂的逻辑,以免影响性能。
  4. 组合使用

    • 在某些复杂场景下,可能需要同时使用防抖和节流,根据具体需求灵活组合使用。

示例:在一个需要同时限制滚动事件频率和搜索输入延迟的场景中,可以分别对滚动事件使用节流,对搜索输入使用防抖。

// 节流处理滚动事件
const handleScrollThrottled = throttle(() => {
    console.log('滚动事件节流处理');
}, 200);

window.addEventListener('scroll', handleScrollThrottled);

// 防抖处理搜索输入
const handleSearchDebounced = debounce((query) => {
    console.log(`搜索内容: ${query}`);
}, 300);

searchInput.addEventListener('input', (e) => {
    handleSearchDebounced(e.target.value);
});

通过合理地组合使用防抖和节流,可以在不同的事件场景中达到最佳的性能优化效果。

防抖和节流是前端开发中优化高频率事件处理的重要技术。

理解它们的概念、区别及实现方法,并在实际开发中合理应用,可以显著提升页面性能和用户体验。

在实际应用中,需根据具体场景选择合适的优化策略,并注意内存管理、函数上下文和参数传递等问题,以确保代码的健壮性和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2296593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言学习笔记:子函数的调用实现各个位的累加和

在C语言程序学习之初&#xff0c;我们都会学习如何打印 hello world&#xff0c;在学习时我们知道了int main&#xff08;&#xff09;是主函数&#xff0c;程序从main函数开始执行&#xff0c;这是流程控制的一部分内容。在主函数中我们想要实现一些功能&#xff0c;比如求各个…

grafana面板配置opentsdb

新增面板&#xff1a; 这里add-panel: 如果不是想新增面板而是想新增一行条目&#xff0c;则点击convert to row: 在新增的面板这里可以看到选择数据源 Aggregator&#xff1a;聚合条件&#xff0c;区分下第一行和第二行的aggregator&#xff0c;第一个是对指标值的聚合&…

2025年02月10日Github流行趋势

项目名称&#xff1a;dify 项目地址url&#xff1a;https://github.com/langgenius/dify项目语言&#xff1a;TypeScript历史star数&#xff1a;64707今日star数&#xff1a;376项目维护者&#xff1a;takatost, crazywoola, laipz8200, iamjoel, JohnJyong项目简介&#xff1a…

Ansible简单介绍及用法

一、简介 Ansible是一个简单的自动化运维管理工具&#xff0c;基于Python语言实现&#xff0c;由Paramiko和PyYAML两个关键模块构建&#xff0c;可用于自动化部署应用、配置、编排task(持续交付、无宕机更新等)。主版本大概每2个月发布一次。 Ansible与Saltstack最大的区别是…

渗透利器工具:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)

Burp Suite 联动 XRAY 图形化工具.&#xff08;主动扫描被动扫描&#xff09; Burp Suite 和 Xray 联合使用&#xff0c;能够将 Burp 的强大流量拦截与修改功能&#xff0c;与 Xray 的高效漏洞检测能力相结合&#xff0c;实现更全面、高效的网络安全测试&#xff0c;同时提升漏…

HTML-day1(学习自用)

目录 一、HTML介绍 二、常用的标签 1、各级标题&#xff08;h1-h6&#xff09; 2、段落标签&#xff08;p&#xff09; 3、文本容器&#xff08;span&#xff09; 4、图片标签&#xff08;img&#xff09; 5、超链接标签&#xff08;a&#xff09; 6、表格&#xff08;t…

Vue07

一、Vuex 概述 目标&#xff1a;明确Vuex是什么&#xff0c;应用场景以及优势 1.是什么 Vuex 是一个 Vue 的 状态管理工具&#xff0c;状态就是数据。 大白话&#xff1a;Vuex 是一个插件&#xff0c;可以管理 Vue 通用的数据 (多组件共享的数据)。例如&#xff1a;购物车数…

Godot开发框架探索#2

前言 距离上次发文又又又隔了很长一段时间。主要原因还是因为思绪在徘徊&#xff0c;最近纠结的点有以下几个&#xff1a;1.渴求一个稳定的Godot开发框架&#xff1b;2.要不要使用更轻量的开发框架&#xff0c;或者直接写引擎&#xff1b; 3.对自己想做的游戏品类拿不定主意。…

deepseek实现私有知识库

前言 之前写了如何本地部署deepseek&#xff0c;已经可以私有化问答了&#xff0c;本地搭建deepseek实操&#xff08;ollama搭建&#xff0c;docker管理&#xff0c;open-webui使用&#xff09; 其中我觉得最厉害的还是这个模型蒸馏&#xff0c;使我们可以用很低的代价使用大模…

【探索未来科技】2025年国际学术会议前瞻

【探索未来科技】2025年国际学术会议前瞻 【探索未来科技】2025年国际学术会议前瞻 文章目录 【探索未来科技】2025年国际学术会议前瞻前言1. 第四届电子信息工程、大数据与计算机技术国际学术会议&#xff08; EIBDCT 2025&#xff09;代码示例&#xff1a;机器学习中的线性回…

大模型基本原理(四)——如何武装ChatGPT

传统的LLM存在几个短板&#xff1a;编造事实、计算不准确、数据过时等&#xff0c;为了应对这几个问题&#xff0c;可以借助一些外部工具或数据把AI武装起来。 实现这一思路的框架包括RAG、PAL、ReAct。 1、RAG&#xff08;检索增强生成&#xff09; LLM生成的内容会受到训练…

开发完的小程序如何分包

好几次了&#xff0c;终于想起来写个笔记记一下 我最开始并不会给小程序分包&#xff0c;然后我就各种搜&#xff0c;发现讲的基本上都是开发之前的小程序分包&#xff0c;可是我都开发完要发布了&#xff0c;提示我说主包太大需要分包&#xff0c;所以我就不会了。。。 好了…

java配置api,vue网页调用api从oracle数据库读取数据

一、主入口文件 1&#xff1a;java后端端口号 2&#xff1a;数据库类型 和 数据库所在服务器ip地址 3&#xff1a;服务器用户名和密码 二、映射数据库表中的数据 resources/mapper/.xml文件 1&#xff1a;column后变量名是数据库中存储的变量名 property的值是column值的…

iOS三方登录 - Facebook登录

引言 在出海APP的开发中&#xff0c;集成主流社交平台的三方登录已成为必不可少的一环。Facebook 作为全球最大的社交网络平台之一&#xff0c;其提供的 Facebook 登录功能能够大大简化用户注册和登录流程&#xff0c;提高用户体验&#xff0c;减少流失率。对于开发者而言&…

机器学习 - 理解偏差-方差分解

为了避免过拟合&#xff0c;我们经常会在模型的拟合能力和复杂度之间进行权衡。拟合能力强的模型一般复杂度会比较高&#xff0c;容易导致过拟合。相反&#xff0c;如果限制模型的复杂度&#xff0c;降低其拟合能力&#xff0c;又可能会导致欠拟合。因此&#xff0c;如何在模型…

深度学习01 神经网络

目录 神经网络 ​感知器 感知器的定义 感知器的数学表达 感知器的局限性 多层感知器&#xff08;MLP, Multi-Layer Perceptron&#xff09; 多层感知器的定义 多层感知器的结构 多层感知器的优势 偏置 偏置的作用 偏置的数学表达 神经网络的构造 ​神经网络的基本…

自动化xpath定位元素(附几款浏览器xpath插件)

在 Web 自动化测试、数据采集、前端调试中&#xff0c;XPath 仍然是不可或缺的技能。虽然 CSS 选择器越来越强大&#xff0c;但面对复杂 DOM 结构时&#xff0c;XPath 仍然更具灵活性。因此&#xff0c;掌握 XPath&#xff0c;不仅能提高自动化测试的稳定性&#xff0c;还能在爬…

PromptSource官方文档翻译

目录 核心概念解析 提示模板&#xff08;Prompt Template&#xff09; P3数据集 安装指南 基础安装&#xff08;仅使用提示&#xff09; 开发环境安装&#xff08;需创建提示&#xff09; API使用详解 基本用法 子数据集处理 批量操作 提示创建流程 Web界面操作 手…

2025年软件测试五大趋势:AI、API安全、云测试等前沿实践

随着软件开发的不断进步&#xff0c;测试方法也在演变。企业需要紧跟新兴趋势&#xff0c;以提升软件质量、提高测试效率&#xff0c;并确保安全性&#xff0c;在竞争激烈的技术环境中保持领先地位。本文将深入探讨2025年最值得关注的五大软件测试趋势。 Parasoft下载https://…

js的DOM一遍过

一、获取元素 1.根据id获取 document.getElementById(id);2.根据标签名获取 使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。 document.getElementsByTagName(标签名);获取某个元素(父元素)内部所有指定标签名的子元素。 element.getElementsByTag…