一、防抖
1.为什么要防抖
有些场景事件的触发频率过高。回调函数执行的频率过高。
2.防抖的原理
控制事件在触发n秒后才去执行(事件处理函数)。如果一个事件在触发的n秒时间内再次触发了,则以最新触发的事件时间为基准,n秒后再执行(事件处理函数),只有在n秒内事件没有再次触发才会执行一次事件处理函数。
官方解释:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
3.代码实现
// 简单的防抖函数(闭包+定时器)
function debounce(func, n) {
let timeOut;
return function () {
// 清除定时器,再重新定义n秒后触发的定时器触发func处理函数
clearTimeout(timeOut);
timeOut = setTimeout(func, n);
};
}
// 事件处理函数
function funcHandler() {
console.log("防抖后的处理函数成功执行!");
}
window.addEventListener("scroll", debounce(funcHandler, 1000));
// this的指向和参数的传递问题
function debounce(func, n) {
let timeOut;
return function () {
let _this = this;
let args = arguments;
// 清除定时器,再重新定义n秒后触发的定时器触发func处理函数
clearTimeout(timeOut);
timeOut = setTimeout(function () {
func.apply(_this, args);
}, n);
};
}
二、节流
1.为什么要节流
图片的懒加载和ajax数据请求加载,有些加载请求不需要太频繁但又要保证页面能正常加载。
2.节流的原理
控制事件处理函数在n秒内只执行一次,即使在这段时间内事件触发多次。在n秒时间内,无论事件触发多少次,只要触发过,则事件处理函数必定执行一次且仅有一次。
官方解释:当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
3.代码实现
// 节流函数(闭包+定时器)
function throttle(func, n) {
let timer = null;
return function () {
let _this = this;
let args = arguments;
// 若定时器变量为假,证明事件还未触发过或者事件触发已经超过至少n秒了
if (!timer) {
timer = setTimeout(function () {
func.apply(_this, args);
timer = null;
}, n);
}
};
}
// 事件处理函数
function funcHandler() {
console.log("节流后的处理函数成功执行!");
}
window.addEventListener("scroll", throttle(funcHandler, 1000));
总结
防抖是控制次数,节流是控制频率。