防抖和节流都是为了限制函数的执行频率。
防抖的意思是,当触发一个事件后,等待一定的时间后才执行函数,如果在此期间又触发了同一事件,则需要重新等待该时间,直到不再触发事件后才会执行函数。防抖主要用在一些频繁触发的事件上,如resize、scroll、input等。
节流的意思是,在一段时间内只执行一次函数。如果在此期间触发了同一事件,该事件会被忽略,直到有一段时间过去后才会再次执行函数。节流主要用在一些需要频繁执行的事件上,比如动画效果、滚动加载等。
下面是用js封装的防抖和节流函数:
防抖函数(debounce)
function debounce(fn, wait) {
let timeout = null;
return function() {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, wait);
};
}
这个函数接收两个参数:fn是需要执行的函数,wait是等待的时间。在函数中,首先通过clearTimeout清除之前设置的timeout计时器,再重新设置一个timeout计时器,并在时间到达后执行传入的函数。
节流函数(throttle)
function throttle(fn, wait) {
let timer = null;
return function() {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, wait);
}
};
}
这个函数也接收两个参数:fn是需要执行的函数,wait是限制的时间。在函数中,首先判断当前是否有一个timer计时器在进行,如果没有,则设置一个timer计时器,并在时间到达后执行传入的函数。如果在此期间又触发了同一事件,则该事件会被忽略。如果只需执行一次,可将timer设置为true。
我们可以将防抖和节流函数封装到一个通用的函数中,让它根据参数来决定使用哪种方式。以下是一个示例代码:
function debounceOrThrottle(func, wait, isDebounce) {
let timeout;
return function() {
const context = this;
const args = arguments;
const later = function() {
timeout = null;
if (!isDebounce) func.apply(context, args);
};
clearTimeout(timeout);
if (isDebounce) timeout = setTimeout(later, wait);
else {
const callNow = !timeout;
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
}
};
}
这个函数接受三个参数:要进行防抖或节流的函数 func
、等待时间 wait
和一个布尔值 isDebounce
,如果为 true
则使用防抖,否则使用节流。
内部创建一个 timeout
变量以跟踪函数上次调用的时间。当调用这个函数时,它会清除之前的 timeout
,创建一个新的 timeout
,并在等待一段时间之后执行 func
。
当 isDebounce
为 true
时,它创建一个防抖函数,在等待时间内只执行最后一次调用。如果 isDebounce
为 false
,则创建一个节流函数,在等待时间内每隔一段时间执行一次调用。
另外,它还返回一个新的函数,在执行时会调用内部创建的防抖或节流函数。