美文网首页
防抖与节流

防抖与节流

作者: 再见噜噜班 | 来源:发表于2019-12-26 20:27 被阅读0次

防抖

在前端开发中,有些事件会持续触发,如scroll,resize事件,如果不停地执行处理函数,则会大大地消耗浏览器性能。这时就需要防抖函数来减少执行函数的频率。
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
防抖函数的原理是:设定一个延时器,在n秒内多次触发事件并不执行函数,而是在每次触发后都重置延时器,将函数延后执行,只有当n秒内不再触发事件,函数才会执行。以scroll事件为例,当我们滚动页面时,会不停地触发scroll事件,但每次触发事件,并不执行函数,而是重置延时器,只有当1秒内不触发事件才会执行函数
实现:

    function debounce(fn,timeout){
        //存储延时器
        let timer
        return function (){
            
            if(timer!==null){
                //防抖函数的代码使用这两行代码来获取 this 和 参数,是为了让 debounce 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。
                let context = this
                let args = arguments
                //当再次触发事件时,如果有延时器存在,就清除当前延时器
                clearTimeout(timer)
                //重置延时器,即再延迟调用事件处理函数,只有当timeout时间内不再触发事件,才会执行函数
                timer = setTimeout(()=>{
                    //使得this不变
                    fn.apply(context,args)
                }, timeout);
            }
            
        }
    }
    function handle(){
        console.log(Math.random())
    }
    window.onscroll=debounce(handle,1000)

节流

类似于防抖,节流是在一段时间内只允许函数执行一次,实现方法可以是时间戳法和定时器法。
实现:

    //时间戳
    /* 1.先记录第一次触发事件的时间prev,
    2.当第二次触发事件时,记录时间now,
    3.判断两次时间间隔是否大于设定的时间,如果小于就不执行函数,等待下一次触发事件,如果大于就执行函数,并将时间轴后移,即把prev的值改为当前时间
    4.回到第一步反复执行 
    特点:第一次触发事件不执行函数,之后不管触发多少次事件,每n秒执行一次函数,最后一次触发事件不会执行*/
    function throttle(fn,wait){
        let prev = Date.now()
        return function (){
            let context = this
            let args = arguments
            let now = Date.now()
            if(now-prev>=wait){
                fn.apply(context,args)
                prev = Date.now()
            }
        }
    }

    function handle(){
        console.log(Math.random())
    }

    let ipt = document.getElementById('ipt')
    ipt.oninput=throttle(handle,3000)

    //定时器
    /* 
    1. 第一次触发事件,设置延时器延时n秒执行函数
    2.第二次触发事件,如果原延时器存在,则不执行函数,等待延时器,如果不存在,则设置延时器延时n秒执行函数
    3.延时器到时间执行函数,并重置延时器为null
    4.重复第一步
    特点:第一次触发事件会延时n秒执行函数,最后一次触发事件也会延时n秒执行函数*/
    function throttle1(fn,wait){
        let timer = null
        return function (){
            let context = this
            let args = arguments
            if(!timer){
                timer = setTimeout(() => {
                    fn.apply(context,args)
                    timer = null
                }, wait);
            }
        }
    }
    let ipt2 = document.getElementById('ipt2')
    ipt2.oninput=throttle1(handle,3000)

相关文章

网友评论

      本文标题:防抖与节流

      本文链接:https://www.haomeiwen.com/subject/bpbloctx.html