【前端面试系列】JavaScript 防抖与节流

server/2024/11/14 12:12:00/

前言

前端开发中,防抖(Debounce)和节流(Throttle)是两种重要的性能优化技术。它们主要用于处理高频触发的事件,如滚动、搜索、窗口调整等。本文将详细介绍这两种技术的原理、实现及应用场景。

一、基本概念

1.1 什么是防抖和节流?

  • 防抖(Debounce): 在事件被触发n秒后再执行回调,如果在这n秒内事件又被触发,则重新计时。
  • 节流(Throttle): 规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行。

1.2 形象比喻

想象一个电梯的运行策略:

  • 防抖: 电梯等待15秒后才运行,期间有人进来则重新计时15秒
  • 节流: 电梯第一个人进来后,15秒后准时运行,不等待

二、防抖(Debounce)实现

2.1 基础版本

javascript">function debounce(func, wait) {let timer = null;return function (...args) {// 清除之前的定时器if (timer) clearTimeout(timer);// 设置新的定时器timer = setTimeout(() => {func.apply(this, args);}, wait);}
}// 使用示例
const handleSearch = debounce(function(e) {console.log('搜索内容:', e.target.value);
}, 500);searchInput.addEventListener('input', handleSearch);

2.2 带立即执行的完整版本

javascript">function debounce(func, wait, immediate = false) {let timer = null;let result;const debounced = function (...args) {// 清除之前的定时器if (timer) clearTimeout(timer);if (immediate) {// 如果是立即执行const callNow = !timer;timer = setTimeout(() => {timer = null;}, wait);if (callNow) {result = func.apply(this, args);}} else {// 延迟执行timer = setTimeout(() => {func.apply(this, args);}, wait);}return result;};// 提供取消功能debounced.cancel = function() {clearTimeout(timer);timer = null;};return debounced;
}

三、节流(Throttle)实现

3.1 时间戳版本

javascript">function throttle(func, wait) {let previous = 0;return function (...args) {const now = Date.now();if (now - previous > wait) {func.apply(this, args);previous = now;}}
}

3.2 定时器版本

javascript">function throttle(func, wait) {let timer = null;return function (...args) {if (!timer) {timer = setTimeout(() => {func.apply(this, args);timer = null;}, wait);}}
}

3.3 结合版本(更精确的节流)

javascript">function throttle(func, wait) {let timer = null;let previous = 0;return function (...args) {const now = Date.now();const remaining = wait - (now - previous);if (remaining <= 0) {// 时间到了,可以执行if (timer) {clearTimeout(timer);timer = null;}func.apply(this, args);previous = now;} else if (!timer) {// 设置定时器,保证最后一次也能执行timer = setTimeout(() => {func.apply(this, args);previous = Date.now();timer = null;}, remaining);}}
}

四、应用场景

4.1 防抖应用场景

  1. 搜索框输入
javascript">const searchInput = document.getElementById('search');
const handleSearch = debounce(async (e) => {const value = e.target.value;const results = await fetchSearchResults(value);updateUI(results);
}, 500);searchInput.addEventListener('input', handleSearch);
  1. 窗口调整
javascript">const handleResize = debounce(() => {console.log('窗口大小改变了!');// 重新计算布局
}, 250);window.addEventListener('resize', handleResize);
  1. 表单验证
javascript">const validateEmail = debounce(async (email) => {const isValid = await checkEmailExists(email);updateValidationUI(isValid);
}, 400);

4.2 节流应用场景

  1. 滚动加载
javascript">const handleScroll = throttle(() => {const { scrollTop, scrollHeight, clientHeight } = document.documentElement;if (scrollTop + clientHeight >= scrollHeight - 20) {loadMoreData();}
}, 200);window.addEventListener('scroll', handleScroll);
  1. 按钮点击
javascript">const button = document.getElementById('submit');
const handleSubmit = throttle(async () => {await submitForm();
}, 1000);button.addEventListener('click', handleSubmit);

五、注意事项

5.1 防抖注意点

  1. 是否需要立即执行
  2. 是否需要取消功能
  3. 返回值的处理
  4. this指向问题

5.2 节流注意点

  1. 首次是否执行
  2. 最后一次是否执行
  3. 时间戳还是定时器方式
  4. 是否需要取消功能

六、最佳实践

  1. 选择合适的时间间隔
javascript">// 搜索框防抖:300-500ms
const searchDebounce = debounce(search, 300);// 滚动节流:100-200ms
const scrollThrottle = throttle(onScroll, 150);
  1. 及时清理
javascript">// React组件示例
useEffect(() => {const handleScroll = throttle(onScroll, 200);window.addEventListener('scroll', handleScroll);return () => {window.removeEventListener('scroll', handleScroll);handleScroll.cancel?.();};
}, []);

总结

防抖和节流都是优化高频率执行代码的手段:

  1. 防抖: 适合连续事件只需要触发一次的场景
  2. 节流: 适合需要定期执行的场景

关键区别:

  • 防抖是在最后一次事件后才执行
  • 节流是在一段时间内只执行一次

选择使用哪种方式,主要取决于具体的业务场景和需求。

写在最后

感谢您花时间阅读这篇文章! 🙏

如果您觉得文章对您有帮助,欢迎:

  • 关注我的技术博客:徐白知识星球 📚
  • 关注微信公众号:徐白知识星球

我会持续输出高质量的前端技术文章,分享实战经验和技术心得。

共同成长

  • 欢迎在评论区留言交流
  • 有问题随时后台私信
  • 定期举办技术分享会
  • 更多精彩内容持续更新中…

让我们一起在技术的道路上携手前行! 💪


http://www.ppmy.cn/server/141857.html

相关文章

Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型多变量回归预测

Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型多变量回归预测 目录 Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 吐血售&#xff01;聚划算&#xff01;Transforme…

基于SpringBoot的垃圾分类回收系统+LW示例参考

1.项目介绍 系统角色&#xff1a;管理员、普通用户、回收员功能模块&#xff1a;管理员&#xff08;用户管理、回收员管理、垃圾类型管理、商品分类管理、环保商城管理、上门回收管理、订单分配管理、订单管理、系统管理等&#xff09;、回收员&#xff08;订单分配、订单管理…

Java开发人员从零学习ArkTs笔记(二)-函数与类

大家好&#xff0c;我是一名热爱Java开发的开发人员。目前&#xff0c;我正在学习ARKTS&#xff08;Advanced Java Knowledge and Technology Stack&#xff09;&#xff0c;并将不断输出我的学习笔记。我将在这里分享我学习ARKTS的过程和心得&#xff0c;希望能够为其他开发人…

ubuntu 安装kafka-eagle

上传压缩包 kafka-eagle-bin-2.0.8.tar.gz 到集群 /root/efak 目录 cd /root/efak tar -zxvf kafka-eagle-bin-2.0.8.tar.gz cd /root/efak/kafka-eagle-bin-2.0.8 mkdir /root/efakmodule tar -zxvf efak-web-2.0.8-bin.tar.gz -C /root/efakmodule/ mv /root/efakmodule/efak…

Python爬虫知识体系-----正则表达式-----持续更新

数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新&#xff1a;https://blog.csdn.net/grd_java/article/details/140574349 文章目录 一、正则基础1. 为什么使用正则2. 正则与re模块简介 二、正则表达式1. 匹配单个字符与数字2. 限定符3. 定位符4. 选择匹…

基于 PyTorch 从零手搓一个GPT Transformer 对话大模型

一、从零手实现 GPT Transformer 模型架构 近年来&#xff0c;大模型的发展势头迅猛&#xff0c;成为了人工智能领域的研究热点。大模型以其强大的语言理解和生成能力&#xff0c;在自然语言处理、机器翻译、文本生成等多个领域取得了显著的成果。但这些都离不开其背后的核心架…

C++(Qt)软件调试---无法校验pdb时间戳(23)

C(Qt)软件调试—无法校验pdb时间戳&#xff08;23&#xff09; 文章目录 C(Qt)软件调试---无法校验pdb时间戳&#xff08;23&#xff09;[toc]1、概述&#x1f41c;2、前期准备&#x1fab2;3、开始分析&#x1f9a7;4、相关地址&#x1f410; 更多精彩内容&#x1f449;内容导…

【论文笔记】The Power of Scale for Parameter-Efficient Prompt Tuning

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: The Power of Scale for P…