ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

防抖与节流

2022-07-22 01:32:45  阅读:202  来源: 互联网

标签:function 触发 防抖 节流 args let timeout fn


  1. 原理:

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

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

    img

  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

标签:function,触发,防抖,节流,args,let,timeout,fn
来源: https://www.cnblogs.com/shallow-dreamer/p/16504200.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有