JavaScript新特性: 一行代码搞定防抖节流

前端开发中常用的性能优化技术:防抖(Debounce)和节流(Throttle),特别是在处理高频触发事件如滚动、调整窗口大小、输入等场景中。传统实现这些功能需要编写复杂的函数,但随着 JavaScript 的发展,我们现在可以通过更简洁的方式实现这些功能。
传统实现方式回顾
在深入新特性之前,让我们先回顾一下传统的防抖和节流实现方式:
传统防抖实现
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);
传统节流实现
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);
JavaScript 新特性:函数装饰器
ECMAScript 的提案中引入了函数装饰器(Function Decorators),这是一种能够在不修改原始函数的情况下增强函数行为的语法。
注意:截至 2024 年 10 月,函数装饰器仍处于 TC39 提案阶段,可能需要通过 Babel 或 TypeScript 等工具进行转译才能使用。
利用装饰器实现一行防抖
class UIutils {
@adebounce(300)
static handleInput(e) {
console.log('处理输入:', e.target.value);
}
}
// 装饰器定义
function debounce(delay) {
return function(target, propertyKey, descriptor){
const original = descriptor.value;
const debounced = function(...args) {
clearTimeout(this._timer);
this.timer = setTimeout(() => {
original.apply(this, args);
}, delay);
};
descriptor.value = debounced;
return descriptor;
};
}
现代化解决方案
使用 requestAnimationFrame 实现的节流
浏览器的requestAnimationFrameAPI 可以帮助我们实现一行代码的节流效果:
// 简洁的 RAF 节流
const throttleRAF = (callback) => {
let ticking = false;
return (...args) => {
if (!ticking) {
ticking = true;
requestAnimationFrame(() => {
callback(...args);
ticking = false;
});
}
};
};
// 一行使用方式
window.addEventListener('scroll', throttleRAF(() => console.log('滚动中')));
利用 AbortController 实现简洁防抖
function debounceWithAbortController(fn,delay) {
let controller = new AbortController();
return function(...args) {
controller.abort();// 取消前一个任务
controller = new Abortcontroller();
const signal = controller.signal;
setTimeout(() => {
if (!signal.aborted) {
fn.apply(this, args);
}, delay);
};
}
// 更简洁的使用方式
const debouncedFn = (fn, delay=300) => {
Let controller;
return (...args) => {
controller?.abort();
controller = new AbortController();
setTimeout(() => !controller.signal.aborted && fn(...args), delay);
};
};
使用 Web Streams API 实现防抖节流
随着 Web Streams API 的成熟,我们可以利用它实现更声明式的防抖和节流:
// 使用 TransformStream 实现防抖
function createDebouncestream(delay) {
let timeout;
return new TransformStream({
transform(chunk, controller) {
clearTimeout(timeout);
timeout = setTimeout(() => {
controller.enqueue(chunk);
}, delay);
});
}
// 使用示例
async function setupDebounceStream() {
const textInput = document.getElementById('search');
const writer = new Writablestream({
write(value) {
console.log('搜索:', value);
});
const inputStream = new ReadableStream({
start(controller) {
textInput.addEventListener('input', event => {
controller.enqueue(event.target.value);
});
}
});
await inputStream
.pipeThrough(createDebouncestream(300))
.pipeTo(writer);
}
第三方库的超简化方案
如果您使用诸如 Lodash、Underscore 等工具库,防抖节流变得极其简单:
// Lodash
import { debounce, throttle } from 'lodash';
// 一行防抖
element.addEventListener('input', _.debounce(handleInput, 300));
// 一行节流
window.addEventListener('scroll', _.throttle(handleScroll, 200));
实际应用场景
- 搜索输入框:防抖可以避免用户每输入一个字符就发送请求
- 窗口调整:节流可以限制布局重新计算的频率
- 无限滚动:节流可以控制加载新内容的频率
- 游戏中的用户输入:确保按键响应不会过于频繁
- 拖拽元素:平滑拖拽效果而不造成性能问题
性能比较
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JavaScript 的发展让我们能够用越来越简洁的代码实现防抖和节流功能。根据项目需求和浏览器兼容性要求,可以选择最适合的实现方式。对于现代 web 应用,装饰器和最新的 Web API 提供了简洁优雅的解决方案;而对于需要广泛兼容的项目,传统实现或借助成熟的第三方库仍然是可靠的选择。
无论选择哪种方式,防抖和节流都是提升用户体验和应用性能的重要技术,所以我们每位前端开发者都必须掌握。
以上关于JavaScript新特性: 一行代码搞定防抖节流的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » JavaScript新特性: 一行代码搞定防抖节流
微信
支付宝