浅谈JavaScript函数的防抖与节流

180 阅读2分钟

不知道防抖与节流,还以为是什么高大上的技术,其实就是控制事件函数触发的时机,因为JavaScript是单线程执行的,触发一个事件,其他异步操作就需要等待,很消耗资源,所以这两个技术就算是优化吧。

示例

很多网站当滚动到页面底部时,右下角会显示回到顶部的按钮,监听了窗口的滚动事件

codesandbox.io/s/brave-tre…

可以看到只要滚一下,就会触发多次,这完全是在消耗资源,那么可以用防抖来处理

防抖

函数防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。这完全可以用定时器实现一个简单的防抖功能

/*
* fn [function] 需要防抖的函数
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
    let timer = undefined //闭包
    return function() {
        if(timer){
           clearTimeout(timer)	// 这里是延时操作
        }
        timer = setTimeout(fn,delay) 
    }
}

使用防抖对上面那个例子进行优化

codesandbox.io/s/elastic-b…

节流

函数节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。就像水龙头那样,将水流速控制,使用定时器实现。

使用场景,比如瀑布流,往下滚动时,每隔一段时间就请求一次Ajax;还有input输入事件,如果不想每输入一个字符就触发一次,也可以用节流。

function throttle(fn,delay){
    let flag = true	// 闭包
    return function() {
       if(!flag){	// 流速控制开关,相当于水龙头
          return false 	// 当flag为false时,即还定时器还没有执行时,直接返回false
       }
        setTimeout(() => {
            fn()
            flag = true	// 定时函数在指定时间执行了就将falg设置为true
        }, delay)
      flag = false	// 定时器设置好后,就将flag设置为false,下次事件触发时,如果定时器还没执行就直接退出
    }
}