在JavaScript的实际开发中,我们经常会遇到一些高频触发的事件,比如输入框实时搜索、窗口滚动监听、按钮连续点击等。如果每次触发事件都直接执行对应的处理函数,会极大消耗浏览器性能,甚至导致页面卡顿。防抖和节流就是为了解决这类问题诞生的两种优化技术,它们通过控制函数的执行频率,减少不必要的计算开销。

什么是防抖
防抖的核心逻辑是:当事件被触发后,不立即执行回调函数,而是设置一个等待时间。如果在等待时间内事件再次被触发,就重新计时,直到等待时间内没有新的事件触发,才执行回调函数。简单来说,就是让函数在事件停止触发一段时间后才执行,适合处理只需要最后一次触发结果的场景。
防抖的实现代码
/**
* 防抖函数
* @param {Function} fn 需要防抖的目标函数
* @param {number} delay 等待时间,单位毫秒
* @returns {Function} 经过防抖处理的函数
*/
function debounce(fn, delay) {
let timer = null;
return function(...args) {
// 如果已有定时器,先清除
if (timer) clearTimeout(timer);
// 重新设置定时器
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
};
}
// 使用示例:输入框搜索联想
const searchInput = document.querySelector('#search-input');
const handleSearch = (value) => {
console.log('搜索关键词:', value);
// 这里可以发起搜索请求
};
// 绑定防抖后的搜索函数,等待500毫秒后执行
searchInput.addEventListener('input', debounce((e) => {
handleSearch(e.target.value);
}, 500));什么是节流
节流的核心逻辑是:在指定时间内,无论事件触发多少次,都只执行一次回调函数。它会保证函数在一段时间内只执行一次,适合处理需要持续触发但不需要高频执行的场景,比如滚动加载、窗口 resize 监听等。
节流的两种实现方式
基于时间戳的节流
/**
* 基于时间戳的节流函数
* @param {Function} fn 需要节流的目标函数
* @param {number} interval 间隔时间,单位毫秒
* @returns {Function} 经过节流处理的函数
*/
function throttleByTimestamp(fn, interval) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
// 如果距离上次执行的时间超过间隔时间,就执行函数
if (now - lastTime >= interval) {
fn.apply(this, args);
lastTime = now;
}
};
}基于定时器的节流
/**
* 基于定时器的节流函数
* @param {Function} fn 需要节流的目标函数
* @param {number} interval 间隔时间,单位毫秒
* @returns {Function} 经过节流处理的函数
*/
function throttleByTimer(fn, interval) {
let timer = null;
return function(...args) {
// 如果定时器不存在,才设置新的定时器
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, interval);
}
};
}节流使用示例
// 滚动加载更多示例
const scrollContainer = document.querySelector('.scroll-container');
const loadMore = () => {
console.log('加载更多内容');
// 这里可以发起加载请求
};
// 绑定节流后的加载函数,每1000毫秒最多执行一次
scrollContainer.addEventListener('scroll', throttleByTimestamp(loadMore, 1000));防抖和节流的区别
两者的核心差异在于执行时机和适用场景,具体对比如下:
| 对比项 | 防抖 | 节流 |
|---|---|---|
| 执行时机 | 事件停止触发一段时间后执行 | 每隔固定时间执行一次 |
| 执行次数 | 连续触发时只执行最后一次 | 连续触发时按固定频率执行 |
| 适用场景 | 输入框搜索、表单验证、窗口 resize 结束后调整布局 | 滚动加载、鼠标移动拖拽、射击游戏射击频率控制 |
实际开发中的选择建议
如果业务需求是只关心最后一次触发的结果,比如搜索联想、表单输入验证,优先选择防抖;如果需求是持续触发但需要控制执行频率,比如滚动监听、实时拖拽位置计算,优先选择节流。在实际项目中,也可以根据需求对两种函数做扩展,比如给防抖增加立即执行的选项,给节流增加首次是否执行的配置,适配更多业务场景。
JavaScript防抖节流性能优化事件处理修改时间:2026-06-06 07:47:36