js防抖与节流
防抖
- 在一定时间内,如果事件一定时间内一直触发的话,只执行最后一次
js
// debounce
let debounce = (fn, delay, immediate = false) => {
let timer = null
return () => {
if(immediate) { // immediate为true表示立即执行一次,后面的再防抖
fn()
immediate = false
}else {
if(timer) clearTimeout(timer) // 清除上一个
timer = setTimeout(() => { // 生成新的
fn()
}, delay)
}
}
}
let fn = () => {
console.log(666)
}
window.addEventListener('scroll', debounce(fn, 1000))
节流
- 如果事件一直触发的话,则间隔一定时间(delay)就执行一次
方案一:时间戳版本
原理: prev为上一次执行时间,如果当前时间减去上一次执行时间大于设置的延时时间就可以触发fn了
js
let throttle = (fn, delay) => {
let prev = Date.now()
return () => {
let now = + new Date()
if(now - prev > delay){ // prev为上一次执行时间,如果当前时间减去上一次执行时间大于设置的延时时间就可以触发fn了
fn()
prev = Date.now() // 重新指定本次调用时间
}
}
}
// 需要多次节流的函数
function fn(){console.log(666)}
window.addEventListener('scroll', throttle(fn, 1000)) // 调用一次,并使用闭包保留了prev
方案二:定时器版本
原理:判断有没有定时器在跑,没有则跑一个
js
let throttle = (fn, delay) => {
let timer = null
return () => {
if(!timer){ // 2.不断地触发,如果timer为null 则注册一个定时器并给timer赋值
timer = setTimeout(() => {
fn()
timer = null // 1.本次执行完成timer置为空
}, delay)
}
}
}
let fn = () => {
console.log(666)
}
window.addEventListener('scroll', throttle(fn, 1000))