面试题---区别函数节流与防抖
1. 事件高频触发处理的问题
- 如果更新界面 => 界面更新卡顿
- 如果发送ajax请求 => 发送了很多没必要的请求
2. 解决办法
- 函数节流
- 函数防抖
3. 区别:
-
节流函数 (throttle):
- 接受两个参数:需要节流的回调函数
callback
和延迟时间delay
。 - 通过保存上一次处理事件的时间
start
,确保在连续触发事件时,只有当当前时间与上一次处理事件的时间差大于设定的延迟时间delay
时,才会执行回调函数callback
。
- 接受两个参数:需要节流的回调函数
-
防抖函数 (debounce):
- 同样接受两个参数:需要防抖的回调函数
callback
和延迟时间delay
。 - 每当事件触发时,如果存在尚未执行的定时器,则清除它,然后重新启动一个延迟时间为
delay
的新定时器。 - 只有当事件触发后,在指定延迟时间内没有再次触发事件时,才会执行回调函数
callback
。
- 同样接受两个参数:需要防抖的回调函数
简单来讲:当事件高频发生很多次时, 防抖只执行最后一次, 而节流执行少量几次
4. 应用场景
节流: 窗口调整(resize)/ 页面滚动(scroll)/ OM元素的拖拽功能实现(mousemove)
防抖: 输入搜索联想功能
5.自定义函数节流与防抖
// 节流函数 (throttle)
function throttle(callback, delay) {
let start = 0; // 用于保存处理事件的时间,初始值为0,保证第一次会执行
// 返回事件监听函数 => 每次事件发生都会执行此返回的函数
return function(event) {
console.log('-- throttle --');
// 发生事件的当前时间
const current = Date.now();
// 与上一次处理事件的时间差大于delay的时间
if (current - start > delay) {
// 执行处理事件的函数
callback.call(event.target, event);
// 保证当前时间为最新的处理事件时间
start = current;
}
}
}
// 防抖函数 (debounce)
function debounce(callback, delay) {
// 返回事件监听函数 => 每次事件发生都会执行此返回的函数
return function(event) {
console.log('-- debounce --');
// 如果还有未执行的定时器,清除它
if (callback.timeoutId) {
clearTimeout(callback.timeoutId);
}
// 启动延迟delay的定时器,并保存定时器id
callback.timeoutId = setTimeout(() => {
// 执行处理事件的函数
callback.call(event.target, event);
// 删除保存的定时器id
callback.timeoutId = null;
}, delay);
}
}
要使用这两个工具函数,可以这样调用它们:
// 假设有一个需要节流的scroll事件处理器
const handleScrollThrottled = throttle(handleScroll, 200);
window.addEventListener('scroll', handleScrollThrottled);
// 假设有一个需要防抖的resize事件处理器
const handleResizeDebounced = debounce(handleResize, 500);
window.addEventListener('resize', handleResizeDebounced);