• 欢迎光临~

防抖与节流

开发技术 开发技术 2022-07-21 次浏览
  1. 原理:

    防抖:在一段时间后执行触发事件,如果在时间内重复触发,则从最后一 次触发开始重新计时,执行。

    节流:在一段时间内执行触发事件,如果在时间内重复触发,在时间内也 只触发一次,执行。

    防抖与节流

  2. 作用:

    本质上是优化高频率执行代码的一种手段。比如:浏览器的resizescrollkeypressmousemove等事件在触发时会不间断的调用绑定在事件上的回调函数,极大地浪费资源,降低性能。为优化体验,需对这类事件进行调用次数的限制,采用防抖(debounce)节流(throttle)的方式来减少调用频率

  3. 代码实现:

    • 节流:节流可以使用时间戳和定时器的写法
    //时间戳写法,如果时间差大于延迟事件会立即执行,停止触发后没有办法再次执行
    function throttled1(fn,delay = 500) {  //设置延迟delay
        let oldtime = Date.now()  //获取当前时间,并存储为oldtime
        return function(...args){
            let newtime = Date.now()  //获取当前时间,并存储newtime
            if(newtime - oldtime >= delay){  //当时间差大于等于延迟时间时,执行触发的函数
                fn.apply(null,args)
                oldtime = Date.now()  //获取当前时间并存储
            }
        }
    }
    
    //定时器写法,delay毫秒后第一次执行,停止触发后事件会再次执行
    function throttled2(fn,delay = 500) {
        let timer = null
        return function(...args) {
            if(!timer){
                timer = setTime(() => {
                    fn.apply(this,args)
                    timer = null
                },delay)
            }
        }
    }
    
    //定时器和时间戳结合的写法,实现更精确的节流
    function throttled(fn,delay) {
        let timer = null
        let starttime = Date.now()
        return function() {
            let curtime = Date.now()  //当前时间
            let remaining = delay - (curtime - starttime)  //从上次到现在,还剩下多少时间
            let context = this
            let args = arguments
            clearTimeout(timer)
            if(remaining <= 0){
                fn.apply(context,args)
                starttime = Date.now()
            }else{
                 timer = setTimeout(fn,remaining)
            }
        }
    }
    
    • 防抖:
    //简单的实现
    function debounce(fn,wait){
        let timeout
        return function(){
            let context = this  //保存this指向
            let args = arguments  //拿到event对象
            clearTimeout(timeout)
            timeout = setTimeout(function(){
                fn.apply(context,args)
            },wait)
        }
    }
    
    //防抖如果需要立即执行,可以加入第三个参数进行判断
    function debounce1(fn,wait,immediate) {
        let timeout
        return function() {
            let context = this
            let args = arguments
            if(timeout) clearTimeout(timeout) //timeout为undefined
      		if(immediate) {
                let callNow = !timeout //第一次立即执行,之后只有事件执行后才会再次触发
                timeout = setTimeout(function(){
                    timeout = null
                },wait)
                if(callNow){
                    fn.apply(context,args)
                }
            }else{
                timeout = setTimeout(function() {
                    fn.apply(context,args)
                },wait)
            }
        }
    }
    
  4. 区别:

    相同点:

    • 都可以通过setTimeout实现
    • 目的都是为了降低回调执行频率,节省计算资源

    不同点:

    • 函数防抖在一段连续的操作结束后,处理回调,利用clearTimeoutsetTimeout实现。函数节流在一段连续的操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。
    • 函数防抖关注一定时间连续触发的事件,只在最后一次执行,而函数节流一段时间内只执行一次。

参考文献:
https://vue3js.cn/interview/JavaScript/debounce_throttle.html
https://blog.csdn.net/buhuidadaima/article/details/115045476

程序员灯塔
转载请注明原文链接:防抖与节流
喜欢 (0)