防抖(debounce)
当 javascript 中函数触发的频率特别高时,我们需要限制它触发的频率。
比如:监听浏览器滚动事件,返回当前滚条与顶部的距离
function showTop () {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
window.onscroll = showTop //当滚动时会很高频率执行
防抖函数分为非立即执行版和立即执行版。
非立即执行版:触发事件后函数不会立即执行,而是在 停止触发行为n秒 后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。立即执行版:触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
//非立即执行版本
function debounce(fn, delay) {
let timeout; // 创建一个标记用来存放定时器的返回值
return function () {
clearTimeout(timeout); // 每当事件触发的时候把前一个 setTimeout clear 掉
timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
fn.apply(this, arguments);
}, delay);
};
}
window.onscroll = debounce(showTop,1000)
//立即执行版本
function debounce(fnc, delay) {
let timeout;
return function () {
clearTimeout(timeout); //每次触发清除上次计时器
if (!timeout) fnc.apply(this, arguments) //如果 timeout 没有重置为 null 则执行函数
timeout = setTimeout(() => { //计时结束后 timeout 置为 null
timeout = null;
}, delay)
}
}
window.onscroll = debounce(showTop, 1000)
返回函数中用 fn.apply(this, argument) 而不直接用 fn(),是为了让 debounce 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。
节流
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
function debounce(fnc, delay) {
let done = 1; //记录是否可执行
return function () {
if(done) {
fnc.apply(this, arguments)
done = 0 //执行后置为不可执行
setTimeout(()=>{ //计时结束后再置为可执行
done =1
}, delay)
}
}
}
window.onscroll = debounce(showTop, 1000)
防抖 和 节流 的区别
比如我们在抢票,我们在狂点 ‘抢票’ 这个按钮
防抖(非立刻执行):不管你狂点多少次,我只等你不狂点了才提交你的最后一次点击
防抖(立刻执行):不管你狂点多少次,我只提交你的第一次
节流:不管你狂点多少次,一定时间内只算你一次