Skip to content

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))