JavaScript 中防抖和节流的多种实现方式及应用场景

笔记哥 / 04-30 / 45点赞 / 0评论 / 996阅读
```csharp ``` 防抖(Debounce)和节流(Throttle)是两种前端开发中常用的性能优化技术,尤其在处理高频触发事件如滚动、调整窗口大小、输入等场景中。传统实现这些功能需要编写复杂的函数,但随着JavaScript的发展,我们现在可以通过更简洁的方式实现这些功能。 ## 传统实现方式回顾 在深入新特性之前,让我们先回顾一下传统的防抖和节流实现方式: ### 传统防抖实现 ```csharp   ``` ```csharp function debounce(fn, delay) { let timer = null; returnfunction(...args) { if (timer) clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); }, delay); }; } // 使用示例 const handleSearch = debounce(function(e) { console.log('搜索内容:', e.target.value); }, 300); searchInput.addEventListener('input', handleSearch); ``` ### 传统节流实现 ```csharp function throttle(fn, delay) { let lastTime = 0; returnfunction(...args) { const now = Date.now(); if (now - lastTime >= delay) { fn.apply(this, args); lastTime = now; } }; } // 使用示例 const handleScroll = throttle(function() { console.log('页面滚动'); }, 200); window.addEventListener('scroll', handleScroll); ``` ```csharp   ``` ## JavaScript新特性:函数装饰器 ECMAScript的提案中引入了函数装饰器(Function Decorators),这是一种能够在不修改原始函数的情况下增强函数行为的语法。 > > > 注意:截至2024年10月,函数装饰器仍处于TC39提案阶段,可能需要通过Babel或TypeScript等工具进行转译才能使用。 > > > ### 利用装饰器实现一行防抖 ![](https://cdn.res.knowhub.vip/c/2505/07/767ea7d9.png?G1cAAER17rxg7QYofice0wSBBJsBizSCSgnr9fz%2f2pfI%2b7lCU7xH69P3h9%2b0Pl3IQisUhWYkhGAgeBh41sCSKxMMFtdw) ## 现代化解决方案 ### 使用requestAnimationFrame实现的节流 浏览器的`requestAnimationFrame`API可以帮助我们实现一行代码的节流效果: ![](https://cdn.res.knowhub.vip/c/2505/07/d0bd9ebf.png?G1cAAMTydJz4u%2feIbqMO3yaKRJsBizSCSgnr9fz%2fPpfI%2b7lCLd6zj%2bXnw2%2f6WC5kYSoUhWYYQkggWFmhFshGJjTLcU8H) ### 利用AbortController实现简洁防抖 ![](https://cdn.res.knowhub.vip/c/2505/07/803c0fc1.png?G1YAAGQ9a5zoqynb6IbeJQ4JzYBEFkGlhPV6792nAXx%2fMLLmZ%2fax4nz4Sx8rgMhIjICRCyqSFyQkK65VkquJu1TLewY%3d) ## 使用Web Streams API实现防抖节流 随着Web Streams API的成熟,我们可以利用它实现更声明式的防抖和节流: ![](https://cdn.res.knowhub.vip/c/2505/07/d14a738e.png?G1cAAMTW3DgpPAJW22gDdWfqnTUDFmkElRLW6%2fn%2ftS%2bi9wth0XyP1mfsD79pfQYBjuIgYTFWpFAYDFMzrQkH9HSv1fMaAQ%3d%3d) ## 第三方库的超简化方案 如果您使用诸如Lodash、Underscore等工具库,防抖节流变得极其简单: ```csharp // Lodashimport { debounce, throttle } from 'lodash';// 一行防抖element.addEventListener('input', _.debounce(handleInput, 300));// 一行节流window.addEventListener('scroll', _.throttle(handleScroll, 200)); ``` ## 实际应用场景 1. 搜索输入框:防抖可以避免用户每输入一个字符就发送请求 2. 窗口调整:节流可以限制布局重新计算的频率 3. 无限滚动:节流可以控制加载新内容的频率 4. 游戏中的用户输入:确保按键响应不会过于频繁 5. 拖拽元素:平滑拖拽效果而不造成性能问题 ## 性能比较 | 实现方式 | 优点 | 缺点 | | --- | --- | --- | | 传统函数封装 | 兼容性好,灵活性高 | 代码冗长,需要手动管理 | | 装饰器 | 语法简洁,声明式编程 | 兼容性问题,需要转译 | | requestAnimationFrame | 与浏览器渲染周期同步,性能好 | 只适用于视觉相关操作 | | AbortController | 清晰地管理取消机制 | 相对新的API,可能需要polyfill | | Web Streams | 声明式,功能强大 | API复杂,兼容性有限 | | 第三方库 | 简单,经过测试 | 增加项目依赖和体积 | JavaScript的发展让我们能够用越来越简洁的代码实现防抖和节流功能。根据项目需求和浏览器兼容性要求,可以选择最适合的实现方式。对于现代web应用,装饰器和最新的Web API提供了简洁优雅的解决方案;而对于需要广泛兼容的项目,传统实现或借助成熟的第三方库仍然是可靠的选择。 无论选择哪种方式,防抖和节流都是提升用户体验和应用性能的重要技术,值得每位前端开发者掌握。