节流(Throttling)和防抖(Debouncing)是JavaScript中常用的两种优化技术,用于限制函数的执行频率,提高应用的性能和响应速度。它们在处理频繁触发的事件(如滚动、窗口调整大小、键盘输入等)时特别有用。
定义
节流(Throttling)
一定时间内只执行一次事件,在一段时间intervalTime
内,不管触发了多少次事件(大于1)都只执行一次。
工作原理
- 时间间隔:设置一个固定的时间间隔(例如100毫秒)。
- 函数执行:在每个时间间隔内,无论事件触发多少次,函数只执行一次。
示例:节流
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => {
inThrottle = false;
}, limit);
}
};
}
// 使用节流处理滚动事件
window.addEventListener('scroll', throttle(() => {
console.log('Scroll event');
}, 100));
这个示例中,throttle
函数确保 scroll
事件处理函数在100毫秒内最多只执行一次。
防抖(Debouncing)
在一定延迟时间内,连续触发的事件合并只执行 最后 一次。如果在指定的时间间隔内事件再次触发,则重新计时。
工作原理
- 延迟时间:设置一个延迟时间(例如300毫秒)。
- 事件触发:新的事件触发时,重新计时。
- 函数执行:如果在延迟时间内没有再次触发事件,则执行函数。
示例:防抖
function debounce(func, delay) {
let inDebounce;
return function() {
const context = this;
const args = arguments;
clearTimeout(inDebounce);
inDebounce = setTimeout(() => {
func.apply(context, args);
}, delay);
};
}
// 使用防抖处理输入事件
const inputField = document.querySelector('input');
inputField.addEventListener('input', debounce((event) => {
console.log('Input event:', event.target.value);
}, 300));
在这个示例中,
函数确保 input
事件处理函数在用户停止输入300毫秒后才执行。
节流 VS 防抖
区别 | 防抖(Debounce) | 节流(throttle) |
---|---|---|
描述 | 一定延迟时间内,连续事件只执行最后一次 | 一段固定时间内只执行一次 |
原理 | 只保留一个延时setTimeout() 的执行器,后续新的替代旧的 | 判断时间间隔,在固定间隔时间内,只执行一次。 |
执行次数 | 只执行最后一次 | 执行首次、最后一次 |
合适场景 | 连续操作只需要一次的,如变更内容提交到后端 | 连续操作定期执行的场景:连续的UI交互,如拖拽、滚动 |
应用场景
节流(Throttling)
- 滚动事件:当用户滚动页面时,频繁触发事件会导致性能问题。节流可以确保在滚动过程中,每隔固定时间只处理一次事件,从而减少性能开销。
- 窗口调整大小:在调整窗口大小时,频繁触发
resize
事件。节流可以确保在调整窗口大小的过程中,每隔固定时间只处理一次事件。 - 鼠标移动事件:在处理鼠标移动事件时,频繁触发事件会导致性能问题。节流可以确保在鼠标移动过程中,每隔固定时间只处理一次事件。
防抖(Debouncing)
- 输入事件:在输入框中输入内容时,频繁触发
input
事件。防抖可以确保在用户停止输入一段时间后才处理事件,从而减少性能开销,适用于搜索建议、自动保存等功能。 - 窗口调整大小:在调整窗口大小时,频繁触发
resize
事件。防抖可以确保在用户停止调整窗口大小一段时间后才处理事件,适用于需要在调整完成后进行布局调整的场景。 - 按钮点击事件:在处理按钮点击事件时,防止用户快速多次点击。防抖可以确保在用户停止点击一段时间后才处理事件,适用于防止表单多次提交等场景。
常见的一些库
Lodash
Lodash 提供的 _.debounce
和 _.throttle
函数可以让我们更方便地实现防抖和节流功能。
节流(Throttling)
import { throttle } from 'lodash';
function handleScroll() {
console.log("Handling scroll event");
// 实际滚动处理逻辑
}
const throttledHandleScroll = throttle(handleScroll, 200);
window.addEventListener('scroll', throttledHandleScroll);
防抖(Debouncing)
import { debounce } from 'lodash';
function logValue(value) {
console.log(`Current value: ${value}`);
}
const debouncedLog = debounce(logValue, 300);
document.getElementById('inputBox').addEventListener('input', function(event) {
const inputValue = event.target.value;
debouncedLog(inputValue); // 使用防抖处理后的函数
});