问题定义
在 Web 开发中,有些事件会频繁触发,例如:
window.resize
:窗口大小改变时触发。scroll
:滚动条滚动时触发。mousemove
:鼠标移动时触发。input
:输入框内容改变时触发。
如果我们在这些事件的回调函数中执行一些耗时的操作,例如发送 AJAX 请求、更新 DOM 等,会导致页面卡顿,影响用户体验。
防抖和节流就是为了解决这个问题,它们可以限制函数的执行频率,提高页面性能。
步骤与流程
1. 防抖 (Debounce)
防抖是指在事件被触发后,延迟一段时间后再执行回调函数。 如果在这段时间内事件再次被触发,则重新计时。 只有当事件停止触发一段时间后,回调函数才会执行。
步骤:
- 定义一个函数,该函数返回一个闭包。
- 在闭包中,使用
setTimeout
设置一个定时器,延迟执行回调函数。 - 如果事件再次被触发,则清除之前的定时器,重新设置定时器。
- 只有当事件停止触发一段时间后,定时器才会执行,回调函数才会执行。
代码示例:
function debounce(func, delay) {
let timer = null;
return function(...args) {
const context = this;
clearTimeout(timer);
timer = setTimeout(function() {
func.apply(context, args);
}, delay);
}
}
2. 节流 (Throttle)
节流是指在一段时间内,只允许回调函数执行一次。 如果在这段时间内事件被触发多次,只有第一次触发会执行回调函数,其他的触发会被忽略。
步骤:
- 定义一个函数,该函数返回一个闭包。
- 在闭包中,使用
setTimeout
设置一个定时器,在定时器执行期间,禁止回调函数再次执行。 - 只有当定时器执行完毕后,才能再次执行回调函数。
代码示例:
function throttle(func, delay) {
let timer = null;
return function(...args) {
const context = this;
if (!timer) {
timer = setTimeout(function() {
func.apply(context, args);
timer = null;
}, delay);
}
}
}
工具与资源
setTimeout
:用于设置定时器。clearTimeout
:用于清除定时器。
注意事项
- 防抖和节流的
this
指向:需要使用apply
或call
改变this
指向。 - 防抖和节流的参数:需要使用
arguments
获取参数。 - 防抖和节流的应用场景: - 防抖适用于只需要执行一次的场景,例如搜索框输入完成后发送 AJAX 请求。 - 节流适用于需要定期执行的场景,例如滚动条滚动时更新页面内容。