防抖
- 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
- 每次触发事件时都取消之前的延时调用方法
function showTop() {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
let timer;
function handle() {
if (timer) {
window.clearTimeout(timer);
}
timer = setTimeout(showTop, 200);
}
window.onscroll = handle;
- 闭包写法
function debounce(fn,delay){
let timer = null //借助闭包
return function() {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fn,delay)
}
}
function showTop () {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
window.onscroll = debounce(showTop,1000)
节流
-
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
-
每次触发事件时都判断当前是否可以执行
function showTop() {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
let flag = true;
function handle() {
if (!flag) {
return;
} else {
flag = false;
setTimeout(() => { showTop(); flag = true; }, 500)
}
}
window.onscroll = handle;
- 闭包写法
function throttle(fn,delay){
let valid = true
return function() {
if(!valid){
return false
}
// 工作时间,执行函数并且在间隔期内把状态位设为无效
valid = false
setTimeout(() => {
fn()
valid = true;
}, delay)
}
}
/* 请注意,节流函数并不止上面这种实现方案,
例如可以完全不借助setTimeout,可以把状态位换成时间戳,然后利用时间戳差值是否大于指定间隔时间来做判定。
也可以直接将setTimeout的返回的标记当做判断条件-判断当前定时器是否存在,如果存在表示还在冷却,并且在执行fn之后消除定时器表示激活,原理都一样
*/
// 以下照旧
function showTop () {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
window.onscroll = throttle(showTop,1000)