前言
最近有一次面试,被狠狠拷打了,尤其是在讨论到页面性能优化时,关于防抖与节流的问题让我措手不及。为了避免再次遇到同样的尴尬,我决定系统地总结这方面的知识,力求简洁明了地分享出来。
认识防抖和节流
防抖(Debouncing)
防抖技术的核心思想是在一个指定的时间间隔内,如果事件被频繁触发,则只有最后一次触发才会执行相应的回调函数。换句话说,它确保了在连续快速的操作中,只执行一次回调。这对于避免不必要的计算或请求特别有用,比如用户在搜索框输入时,我们不希望每次按键都发送请求,而是等待用户停止输入一段时间后再发送。
节流(Throttling)
不同于防抖,节流限制了一个函数在一定时间内的调用次数。即无论事件被触发多少次,在规定的时间间隔内只会执行一次回调。例如,在处理滚动事件时,我们可以设置每秒只响应一次,从而减少浏览器的负担。
这两种技术的区别
- 防抖:就像游戏里面的回城操作,如果在回城时间内再次点击回城(回城被打断),则会重新计算回城时间。也就是说,防抖会在你停止操作后的一段时间才执行。
- 节流:类似于游戏里英雄的普通攻击,在一定时间内点击多次,也只能攻击一次。这意味着在设定的时间间隔内,即使事件被多次触发,也只会执行一次回调。
使用场景分析
-
防抖:
- 搜索框自动完成建议:用户输入完毕后延迟一段时间再发送请求,避免每次按键都发送请求。
- 表单验证:在用户停止输入后进行表单验证,而不是每次按键都验证。
- 窗口大小调整:在用户停止调整窗口大小后执行相应的布局调整代码。
-
节流:
- 页面滚动加载更多内容:当用户滚动页面时,每隔一定时间检查是否需要加载更多数据。
- 鼠标移动事件:在游戏中跟踪玩家的鼠标移动,但不需要对每一次微小的移动都做出反应。
- 触摸屏滑动:在触摸屏设备上,监听用户的滑动操作,但不需要对每一个细微的触摸点变化都做出响应。
实现防抖
防抖的实现原理非常简单,就是通过对要执行的函数进行延迟处理,以此来控制函数执行的次数。
具体流程如下:
- 定义
debounce
函数 :接受两个参数,一个是需要执行的函数func
,另一个是等待的时间wait
。 - 内部逻辑 :
- 使用
let timeout;
来存储定时器ID。 - 返回一个新的函数,每当触发事件时调用此函数。
- 在每次调用返回的函数时,首先清除之前设置的定时器(如果有)。
- 设置一个新的定时器,在指定的
wait
时间后执行传入的func
函数,并使用apply
方法确保正确的上下文(this
指向)和参数传递。
- 使用
- 应用示例:将防抖函数应用于窗口大小调整事件,确保在用户停止调整窗口大小后3秒才执行回调。
js
// 防抖
function debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
window.addEventListener('resize', debounce(() => {
console.log('window resize');
}, 3000));
实现节流
节流技术的实现原理也非常简单,就是通过设置一个固定时间间隔,在这个时间间隔内只能执行一次相应的回调函数。
具体流程如下:
- 定义
throttle
函数 :接受两个参数,一个是需要执行的函数func
,另一个是限制的时间间隔limit
。 - 内部逻辑 :
- 使用
let lastExecutionTime = 0;
来记录上一次执行的时间戳。 - 返回一个新的函数,每当触发事件时调用此函数。
- 在每次调用返回的函数时,获取当前时间
now
。 - 如果当前时间减去上次执行的时间大于或等于设定的
limit
,则执行传入的func
函数,并更新lastExecutionTime
为当前时间。
- 使用
- 应用示例:将节流函数应用于滚动事件,确保每3秒内最多执行一次回调。
js
// 节流
function throttle(func, limit) {
let lastExecutionTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastExecutionTime >= limit) {
func.apply(this, args);
lastExecutionTime = now;
}
};
}
document.getElementById('scrollArea').addEventListener('scroll', throttle(() => {
console.log('scroll event throttled');
}, 3000));
结语
掌握这些技巧不仅能够让你的网页运行得更加流畅,还能在面试中展现出你的专业水平和技术深度。希望本文能为你的前端开发之路提供一些有价值的参考!