防抖和节流的出现,都是为了解决事件触发十分频繁的问题。
个人认为,节流是防抖的优化,因为防抖只能做到在一段时间内,事件不会一直触发,但是要是一直进行触发这个事件的操作,那么根据防抖的设计,计时器就会一直刷新,导致事件一次也触发不了。
下面直接上代码吧。
防抖实现:
function fangDou(fn, delay) {
let time = null
return function() {
if (time) clearTimeout(time) // 如果time存在,就说明定时器已经触发过一次了,清除还未执行的定时器,然后下面再起一个新的定时器来执行方法
time = setTimeout(fn, delay)
}
}
function scroll() {
console.log('top', document.body.scrollTop, document.documentElement.scrollTop)
}
window.onscroll = fangDou(scroll, 1000) // 如此就能保证,触发滚动时,在1秒内,如果不再操作,就会触发一次打印top的方法
// 要是一直操作的话,将一次也触发不了。并且这种写法存在执行延迟的问题。
//下面再写一个能立即执行的防抖
function fangDou(fn, delay) {
let time = null
return function() {
if (time) clearTimeout(time)
let now = !time
time = setTimeout(() => time = null, delay)
if (now) fn()
}
}
function scroll() {
console.log('top', document.body.scrollTop, document.documentElement.scrollTop)
}
window.onscroll = fangDou(scroll, 1000) // 这样写只是比上面的写法多了一次立即执行,要是一直操作,之后还是不会触发方法
节流实现
function jieLiu(fn, delay) {
let valid= true
return function() {
if (!valid) return // 上次触发到现在还没有一次delay的时间,什么操作都没有,直接返回
valid = false
fn()
setTimeout(() => valid = true, delay)
}
}
function scroll() {
console.log('top', document.body.scrollTop, document.documentElement.scrollTop)
}
window.onscroll = jieLiu(scroll, 1000)
上述方法除了定时器,也可以用时间戳来实现,根据new Date()或Date.now()获得当前的时间,来判断是否满足比如已经过了一秒的条件,然后再决定要不要触发方法。思路都是一样的。