防抖和节流

4 阅读2分钟

前端有很多频繁触发的事件,例如:input,scroll,resize等,频发触发事件会造成不必要的性能浪费,为了避免这种情况经常采用防抖和节流的方式来处理,这里可以根据自己的需要来进行选择.因为之前也对防抖和节流的概念有所混淆,所以现在也想将自己的理解分享下.

对防抖和节流的理解

防抖: 事件触发n秒后执行,如果在n秒内再次触发了事件,重新计时n秒后执行(一直执行,一直不触发)

节流: 事件n秒内只执行一次,在本次n秒过后才会再次执行一次(稀释事件频率)

防抖函数

function debounce(fun, wait=500) {
    // 创建timer,使用到闭包去保存,这样下次执行时也可以获取到timer
    let timer
    // 返回的方法是触发的事件,我们需要在这个方法里调用我们真正的逻辑事件,即fun
    return function (...args) {
        // 及时清理没有执行的延时器,保证最后一次触发后n秒才会执行事件
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
            // 延时n秒后触发事件
            // 修改事件中的this,并将相应的参数传递给事件,比如event
            fun.apply(this, args)
        }, wait)
    }
}

节流函数

// 根据时间戳计算时间差,来判断是否触发逻辑
function throttle1(fun, wait=500) {
    // 闭包保存初始时间
    let startTime = 0
    return function(...args) {
        let nowTime = Date.now()
        // 获取当前时间,计算出时间差
        if (nowTime - startTime > wait) {
            // 当时间差大于节流设置的时间间隔,触发真正的逻辑
            fun.apply(this, args)
            // 给初始时间赋值,以计算下次执行的时间
            startTime = nowTime
        }
    }
}
// 利用延时器控制逻辑触发
function throttle2(fun, wait=500) {
    // 闭包保存保存延时器的变量
    let timer
    return function(...args) {
        if (!timer) {
            // 延时器不存在的时候,设置n秒后触发真正逻辑
            // 延时器存在说明已经有在等在执行的逻辑
            timer = setTimeout(() => {
                fun.apply(this, args)
                // 执行后,恢复初始值,下次再次执行
                timer = null
            }, wait)
        }
    }
}

两个节流函数使用效果的区别: 1触发事件后会立刻执行一次,停止触发事件后不在执行 2触发事件后不会立即执行,要在n秒后执行第一次,停止触发后会在触发一次事件