一、什么是防抖和节流呢?
防抖(debounce)和节流(throttle)都是用于控制函数在频繁出发时的执行次数的技术,主要用于优化性能以及减少不必要的资源消耗,区别在于执行的时机和策略不同
- 举个例子
<div id="shake">测试盒子</div>
<script>
let num = 1;
const content = document.getElementById('shake');
function count() {
content.innerHTML = num++;
};
content.onmousemove = count;
</script>
注意:上面例子中鼠标只要在div区域内一移动,count函数就会被执行,num就会增加,这时候就需要用上防抖和节流了
二、防抖
1、什么是防抖
- 执行时机 : 防抖主要思想就是当时间触发之后,等待一定的时间间隔,如果在这个时间间隔内没有再次触发事件,才会执行函数,如果在这个时间间隔内再次触发了事件就重新开始计时
- 应用场景 :用户输入,当用户在搜索框中输入时,可以等待用户停止输入一段时间后再次执行搜索操作,而不是每次输入都立即发起搜索请求
- 实现方式 :可以使用setTimeout实现防抖,每次事件触发时,清除之前的定时器,并设置一个新的定时器,当定时器到期时执行函数
1、实现防抖
// setTimeout实现防抖
function debounce(func, delay) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func(...args);
}, delay);
};
}
<script>
let num = 1;
const content = document.getElementById('shake');
function count() {
content.innerHTML = num++;
};
function debounce(func, wait) {
let timer;
return function () {
const context = this;
const args = [...arguments];
if (timer) clearTimeout(timer);
// 只有在newNow值为true时才会触发功能函数![在这里插入图片描述](https://img-blog.csdnimg.cn/0332f980333548938176e881e7fddf5a.png)
const newNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait);
if (newNow) func.apply(context, args);
};
}
content.onclick = debounce(count,1000);
</script>
- 触发debounce事件后函数会立即执行,n 秒内触发事件不会执
行功能函数下一次调用,n秒后再次触发才会再次执行函数 - 在时间间隔内如果再次调用debounce函数,这时已经有定时器在了,要即使清除定时器,但定时器标识符timer还在,所以newNow的值是false,所以不能触发功能函数
- 定时器间隔失效后再去执行这个定时器,将定时器标识符timer设置为null
- 最后调用debounce函数,让newNow的值为true
三、节流
1、什么是节流
- 执行时机 :节流主要思想是无论事件触发多少次,都限制函数的执行频率,在一定时间间隔内只执行一次
- 应用场景 :适用于需要限制某个操作的执行频率,例如滚动事件、鼠标移动事件
- 实现方式 :可以使用时间戳来实现节流,记录上次执行函数的时间,每次事件触发时,检查当前时间与上次执行时间的间隔,如果大于指定的时间间隔就执行函数
1、实现节流
- 时间戳实现节流:时间段内开始的时候触发功能函数
function throttle(func, delay) {
let lastExecTime = 0;
return function (...args) {
const currentTime = Date.now();
if (currentTime - lastExecTime >= delay) {
func(...args);
lastExecTime = currentTime;
}
};
}
content.onmousemove = throttle(count,1000);
- 定时器实现节流
function throttle(func, wait) {
let timer ;
return function() {
let context = this;
let args = arguments;
if (!timer ) {
timer = setTimeout(() => {
timer = null;
func.apply(context, args)
}, wait)
}
}
}
四、防抖与节流有什么区别呢?
- 执行次数 :防抖在一段时间内只执行一次函数;节流在一定时间内可以执行多次函数,但是会控制执行效率
- 定时器 vs 时间戳 :防抖使用定时器控制函数的执行,节流使用时间戳控制函数执行
- 延迟执行 vs 立即执行 :防抖在时间停止触发后延迟一段时间再执行函数;节流在事件触发时立即执行函数,但限制了执行频率
选择防抖还是节流取决于具体的需求喝应用场景
如果需要确保事件的最后一次触发后再执行操作,通常选择防抖;
如果需要限制事件处理的频率,通常选择节流;