防抖
- 场景
当实现滚动监听的时候,发现每滚动一次滚动条,这个监听时间执行了十来次,如果这样子实现太过于浪费性能,所以就出现了防抖。
- 那么这个问题怎么优化呢?
当我们滚动监听第一次触发的时候不是立即执行函数,而是给它一个delay延迟时间,比如200ms
- 当在200ms内如果没有触发该事件,则执行函数
- 在200ms再次或者多次触发,都清空定时器,重新设置定时器知道过了delay时间后才执行函数。
大概思路是这样,那么应该怎么用代码来实现呢,用setTimeout来实现定时器的功能
function debounce(fn, delay) {
let timer = null;
return () => {
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(fn. delay);
}
}
const showTop = () => {
console.log('scrollTop', document.body.scrollTop);
};
document.body.onscroll = debounce(showTop, 1000);
节流
- 场景
监听滚动条,只要滚动函数就会执行,有时候执行了十来次,这个时候就需要优化。
- 怎么优化呢,接下来说一下实现思路
让函数执行一次后,在某个时间段内暂时失效,等过了这个时间段再激活生效。
短时间内大量触发同一事件,函数执行一次后再指定的时间内不会再执行,等到过了指定的时间段后才会重新生效。
- 代码实现 状态位/setTimeout
// 状态位实现
function throttle(fn, delay) {
let valid = true;
return () => {
if (!valid) return false;
valid = false; // 执行函数,状态设置为无效
setTimeout(() => {
fn();
valid = true; // 函数执行完毕,状态激活
}, delay);
}
}
// setTimeout实现
function throttle(fn, delay) {
let timer = null;
return () => {
if (!timer) {
timer = setTimeout(() => {
fn();
timer = null;
}, delay)
}
}
}