初探前端优化——节流(throttle)与防抖(debounce)

950 阅读2分钟

防抖节流平时前端项目上面用的不少,今天来初步介绍一下。

1.什么是防抖与节流

  • 防抖

    防抖就是要执行方法和行为的时候,会在开始的时候开启一个倒计时,在这个倒计时时间内如果又执行了方法和行为,那么这个倒计时清空,重新开始倒计时,这个倒计时全局只有一个,倒计时结束时,才会执行你想执行方法的内容。

    防抖常用于监听用户对浏览器resize,scroll等操作,我们不可能对于用户频繁的操作(间隔极短),都会执行我们的回调函数,这样对浏览器的性能销毁是巨大的,为了避免这个问题我这里写了个基本的scroll防抖回调函数。

demo代码

//防抖函数
function debounce(func, wait) {
    if(typeof func !== 'function') {
        throw new TypeError('need a function')
    }
    let timeId = null
    return function() {
        console.log('滚动了滚动了')
        if(timeId) clearTimeout(timeId)
        timeId = setTimeout(() => {
            func.apply(this, arguments)
        }, wait);
    }
}
//scrollhandler
function scrollHandler(e) {
    console.log("触发滑动scroll", e)
}
document.addEventListener('scroll', debounce(scrollHandler, 2000))

运行结果

image.png

  • 节流

    节流就是在特定间隔时间段内, 无论用户要执行方法和行为多少次,只能执行一次方法内容。

    节流常用于用户通过按钮点击或者输入框输入,要执行一些耗时代码或者异步代码。用户频繁点击或者输入就会导致多次发起请求或者耗时,导致性能开销大。

    demo代码

//节流
function throttle(func, gapTime) {
    if(typeof func !== 'function') {
        throw new TypeError('need a function')
    }
    let lastTime = 0
    console.log("疯狂点击")
    return function() {
        const time = +new Date()
        if(time - lastTime > gapTime) {
            func.apply(this, arguments)
            lastTime = time
        }
    }
}

document.querySelector('#btn').addEventListener('click', throttle(clickHandler, 2000))

运行结果

image.png

  • 这里为什么要用到闭包呢?

因为定义的timeId变量,在一般的函数中在执行完以后会被释放,如果return 一个匿名函数,如果匿名函数中继续引用该变量,形成了闭包,此变量是是不会被销毁回收的,一直存在内存中。所以就能判断倒计时setTimeout是否存在,存在则清除,不存在则重新创建。