手写函数节流
在前端开发中,我们经常遇到需要对某些频繁触发的事件(如窗口的resize、scroll事件,或者高频率的按钮点击)进行限制,以避免因函数执行过于频繁而导致的性能问题。这时,一个非常有用的工具就是**函数节流**(throttle)。本文将深入探讨函数节流的概念、原理,并手把手教你如何实现一个简单的函数节流。
函数防抖,顾名思义,就是当持续触发事件时,只有事件停止触发 n
秒后才执行,如果这 n
秒内又触发了事件,则会重新计算延时。
函数防抖的核心在于使用setTimeout来延迟函数的执行,并在每次调用时取消之前的延时调用,从而确保只有最后一次操作能触发函数执行。
下面是一个简单实用的防抖函数实现:
function debounce(func, wait) {
let timer;
// 用于存储setTimeout的返回值,以便于 clearTimeout
return function(...args) {
if (timer) {
// 如果已有定时器,则清除它
clearTimeout(timer);
}
timer = setTimeout(() => {
// 重新设置定时器
func.apply(this, args);
// 在延迟时间结束后执行原函数
}, wait);
};
}
在这个实现中,debounce
函数接收两个参数:一个是需要防抖处理的函数func
,另一个是延迟执行的时间wait
(单位为毫秒)。内部返回一个新的函数,这个新函数会在每次被调用时清除之前的延时调用,并重新设置一个延时执行的定时器。当延时期限到达且没有新的调用时,原始函数func
才会被执行。
相比于一个周期最后一次触发后,等待一定的时间在执行目标函数,我们需要实现一个在一个周期内容第一次触发,就立即执行一次,然后在触发后,等待一定的时间,才执行目标函数。这样的体验会更好。
function debounce(fn, wait, immediate) {
let timer;
let _debounce = function () {
let context = this;
if (timer) {
clearTimeout(timer);
}
if (immediate) {
let callNow = !timer;
if (callNow) {
func.apply(context, arguments);
}
timer = setTimeout(function () {
timer = null;
}, wait);
} else {
timer = setTimeout(function () {
func.apply(context, arguments);
}, wait);
}
}
return _debounce;
}