在JS中,当事件触发很频繁,浏览器来不及处理时,就会导致页面出现卡顿的现象,解决这种卡顿问题,就需要用到了防抖和节流。
防抖和节流就是针对响应跟不上触发频率这类问题解决方案。
1、含义
防抖(debounce) 策略是,当事件被触发时,设定一个周期延迟执行动作,若期间又被触发,则重新设定周期,直到周期结束,执行动作。
节流(throttle) 策略是,在固定周期内,只执行一次动作,若有新事件触发,不执行,周期结束后,又有事件触发,开始新的周期。即:高频事件触发,但是在n秒内只会执行一次,会稀释函数的执行频率
2、实现原理:
防抖,维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置,这样一来,只有最后一次操作能被触发。
节流,通过判断是否到达一定时间来触发函数。有2种实现方式:时间戳和定时器,用时间戳实现的函数触发是在时间段内开始的时候,而定时器实现的函数触发是在时间段内结束的时候触发。
3、区别:
节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而防抖只是在最后一次事件后才触发一次函数。
4、使用场景:
用防抖:当程序只需要处理最后一次触发事件时。
比如:1)在输入框反复输入内容,输入结束后再执行操作;2)浏览器出口大小变化时,不需要计算中间的变化过程,只需要窗口大小改变完成后的值。
用节流: 当事件触发过于频繁,需要限制事件处理程序的调用频率时。
比如:1)滚动加载,如是否滑到底部自动加载更多;2)鼠标不断点击触发,mousedown(单位时间内只触发一次) ;3)高频点击提交,表单重复提交。
5、实现:
/**
* @description: 防抖,触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
* @param {Function} func 方法
* @param {Number} delay 时间(单位:秒)
* @return 无
*/
function debounce(func, delay) {
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, arguments);
}, delay);
};
}
/**
* @description: 节流,高频事件触发,但在n秒内只会执行一次
* @param {Function} func 方法
* @param {Number} delay 时间(单位:秒)
* @return 无
*/
function throttle(func, delay) {
let flag = true;
return function () {
if (!flag) {
return;
}
flag = false;
setTimeout(() => {
func.apply(this, arguments);
flag = true;
}, delay);
};
}
/**
* @description: 节流(时间戳),高频事件触发,但在n秒内只会执行一次
* @param {Function} func 方法
* @param {Number} delay 时间(单位:秒)
* @return 无
*/
function throttle2(func, delay) {
let previous = 0;
return function () {
let now = Date.now();
if (now - previous > delay) {
func.apply(this, arguments);
previous = Date.now();
}
};
}