前端性能优化之防抖与节流原理与实现详解
字数 597 2025-11-19 17:10:48
前端性能优化之防抖与节流原理与实现详解
一、概念描述
防抖和节流是前端性能优化中常用的两种高频事件处理技术,主要用于控制函数执行频率,避免频繁操作导致的性能问题。
二、防抖详解
-
核心思想
在事件被触发n秒后再执行回调,如果在这n秒内事件又被触发,则重新计时 -
应用场景
- 搜索框输入联想(等待用户停止输入后再发送请求)
- 窗口大小调整(调整结束后再计算布局)
- 表单验证(输入完成后再验证)
- 实现步骤
function debounce(func, delay) {
let timeoutId;
return function(...args) {
// 清除之前的定时器
clearTimeout(timeoutId);
// 设置新的定时器
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
- 执行过程分析
- 第一次触发:设置定时器,delay毫秒后执行
- 在delay时间内再次触发:清除前一个定时器,重新设置定时器
- 停止触发后:最后一次设置的定时器触发,函数执行
三、节流详解
-
核心思想
在规定时间间隔内只执行一次函数,稀释函数执行频率 -
应用场景
- 滚动加载(每隔固定时间检查位置)
- 按钮防重复点击
- 鼠标移动事件
- 时间戳实现
function throttle(func, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
// 如果距离上次执行时间超过delay,则执行
if (now - lastTime >= delay) {
func.apply(this, args);
lastTime = now;
}
};
}
- 定时器实现
function throttle(func, delay) {
let timeoutId;
return function(...args) {
if (!timeoutId) {
timeoutId = setTimeout(() => {
func.apply(this, args);
timeoutId = null;
}, delay);
}
};
}
四、进阶实现与优化
- 带立即执行选项的防抖
function debounce(func, delay, immediate = false) {
let timeoutId;
return function(...args) {
const callNow = immediate && !timeoutId;
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
timeoutId = null;
if (!immediate) {
func.apply(this, args);
}
}, delay);
if (callNow) {
func.apply(this, args);
}
};
}
- 带取消功能的节流
function throttle(func, delay) {
let timeoutId;
let lastTime = 0;
const throttled = function(...args) {
const now = Date.now();
const remaining = delay - (now - lastTime);
if (remaining <= 0) {
// 时间间隔已到,立即执行
func.apply(this, args);
lastTime = now;
} else if (!timeoutId) {
// 设置剩余时间后执行
timeoutId = setTimeout(() => {
func.apply(this, args);
lastTime = Date.now();
timeoutId = null;
}, remaining);
}
};
throttled.cancel = function() {
clearTimeout(timeoutId);
timeoutId = null;
lastTime = 0;
};
return throttled;
}
五、实际应用示例
- 搜索框防抖应用
const searchInput = document.getElementById('search');
const debouncedSearch = debounce(searchAPI, 300);
searchInput.addEventListener('input', debouncedSearch);
async function searchAPI(query) {
const response = await fetch(`/api/search?q=${query}`);
// 处理搜索结果
}
- 滚动节流应用
const throttledScroll = throttle(checkPosition, 100);
window.addEventListener('scroll', throttledScroll);
function checkPosition() {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 500) {
loadMoreContent();
}
}
六、性能对比与选择策略
- 防抖适用场景
- 关注结果,不关注过程
- 需要等待用户操作停止后再执行
- 避免重复请求
- 节流适用场景
- 保持固定的执行频率
- 保证用户体验的流畅性
- 避免过于频繁的UI更新
七、现代浏览器原生支持
现代浏览器提供了原生的节流支持:
// 使用requestAnimationFrame实现节流
function rafThrottle(func) {
let ticking = false;
return function(...args) {
if (!ticking) {
requestAnimationFrame(() => {
func.apply(this, args);
ticking = false;
});
ticking = true;
}
};
}
通过合理使用防抖和节流,可以显著提升前端应用的性能和用户体验,特别是在处理高频事件时效果尤为明显。