防抖与节流

163 阅读2分钟

防抖

理解

在一段时间中只执行一次

在事件被触发时,延迟n秒后再触发回调函数,如果n秒内又触发了事件,则会重新开始计算时间(n秒内最后一次生效)

使用场景

  • 输入框输入

  • 缩放resize 浏览器缩放,重新渲染表格

定时器版

青春版

function debounce(){
     let timer//使用到了闭包
     return ()=>{
       clearTimeout(timer)//清除定时器
       timer=setTimeout(()=>{//设置定时器
          console.log('执行一次')
       },1000)
    }
}

debounce()

完整版

function addOne(){
    console.log('执行一次',arguments[2])
}
function debounce(fn,time){
     let timer
     return ()=>{
       clearTimeout(timer)
       timer=setTimeout(()=>{
          fn.apply(this,arguments)//改变this和传入参数
       },time)
    }
}

debounce(addOne,1000,'!!!')

节流

理解

每间隔一段时间执行一次

一段时间内只能触发一次,如果这段时间内触发多次事件,只有第一次生效会触发回调函数,一段时间过后才能再次触发(n秒内第一次生效)

使用场景

  • 鼠标点击,- 鼠标按下和鼠标悬停单位时间只执行一次

  • 滚动事件,懒加载、滚动加载、加载更多或监听滚动条位置

  • 防止高频点击提交,防止表单重复提交

定时器版

青春版

function throttle(){
     let timer = null
     return ()=>{
        if(!timer){//如果定时器不存在,则执行一次,并产生一个定时器
            console.log('执行一次')
            timer = setTimeout(()=>{
                timer = null//置为null,相当于清除定时器
            },1000)
        }
    }
}

throttle()

完整版

function addOne(){
    console.log('执行一次',arguments[2])
}
function throttle(fn,time){
     let timer = null
     return ()=>{
        if(!timer){
            fn.apply(this,arguments)//改变this和传入参数
            timer = setTimeout(()=>{
                timer = null
            },time)
        }
    }
}

throttle(addOne,1000,'!!!')

时间戳版

青春版

function throttle(){
     let last = 0
     return ()=>{
        let now = Date.now()
        if(now - last > 1000){
            console.log('执行一次')
            last = now
        }
    }
}

throttle()

完整版

function addOne(){
    console.log('执行一次',arguments[2])
}
function throttle(fn,time){
     let last = 0
     return ()=>{
        let now = Date.now()
        if(now - last > time){
            fn.apply(this,arguments)
            last = now
        }
    }
}

throttle(addOne,1000,'!!!')