节流与防抖

1.我们先了解为什么要节流和防抖

我们给一个inpu输入框绑定一个oninput事件,此时我们输入“前端开发”四个字,我们

观察以下后台打印





    
    
    
    Document



    
    


节流与防抖_第1张图片

 我们仅仅输入四个字,就触发了几十次事件,

如果说我每一次输入都和后台进行数据交互,那么将会很影响计算机的性能。

因此我们需要让请求的次数大大减少,因此我们需要利用防抖来减少用户操作过多,与后台数据交互的次数。

接下来我们来介绍防抖

2.防抖

防抖:用户触发事件过于频繁,只要最后一次事件的操作。

也就是说,用户频繁的操作,我们只取最后一次操作。

比如

同样我们输入‘前端开发’四个字,如果我们输入的时间间隔小于0.5秒,就不触发oninput事件,

如果我们输入的时间间隔大于0.5秒,那么我们就触发oninput。

这样我们就大大减少了请求的次数。





    
    
    
    Document



    
    


节流与防抖_第2张图片

 如图,我们只要输入的时间间隔小于0.5秒,就不会触发oninput事件,只有当我们的输入的时间间隔超过0.5秒时,才会触发该事件。对比之下,我们触发的次数少了很多。

虽然以上代码完成了防抖的效果,但是还可以再优化一下,为什么要优化呢

在我们写的代码中只有console.log(this.value) 是真正的业务逻辑代码

 而且我们还定义了一个全局变量t,

以及这部分是防抖代码和业务代码混在一起,

           //防抖的逻辑和业务逻辑混在一起了
             if (t !== null) {
                clearTimeout(t)
            }
            t = setTimeout(() => {
                console.log(this.value) //真正的业务逻辑代码
            }, 500)

,而且该部分代码可读性不太好,别人需要看半天才知道是防抖,因此我们需要优化一下。 

我们可以通过闭包来优化防抖代码

使用闭包可以不用产生全局变量t,并且可以让防抖代码与业务代码隔离;





    
    
    
    Document



    
    


很多人看到这里可能一头雾水,突然有点看不懂了,别着急,我来慢慢解释。

这里我们定义了一个防抖函数debounce

  inp.oninput = debounce();


   function debounce() {//防抖函数
            return function() {
               
            }
        }

我们知道inp.oninput事件=一个函数,

所以debounce返回一个函数,并且我们需要将相关逻辑作为参数,传给debounce

inp.oninput = debounce(function(){},500);//参数function(){}中执行业务代码,500是传入的延时时间


   function debounce(fn,delay) {//fn是要执行的业务逻辑,是函数//delay为定时器的延时事件
            let t=null;
            return function() {
               if (t !== null) {
                    clearTimeout(t)
                }
                t = setTimeout(() => {
                    fn(); //执行的业务代码
                }, delay)
            }
        }

接着

 inp.oninput = debounce(function() {
            console.log(this.value)
        }, 500);

        function debounce(fn, delay) {
            let t = null;
            return function() {
                if (t !== null) {
                    clearTimeout(t)
                }
                t = setTimeout(() => {
                    fn();
                }, delay)
            }
        }

我们运行一下代码,输入

发现输出的是undefind 

节流与防抖_第3张图片
 我们打印一下this,发现打印的是window,

 inp.oninput = debounce(function() {
            console.log(this)//打印this
        }, 500);

        function debounce(fn, delay) {
            let t = null;
            return function() {
                if (t !== null) {
                    clearTimeout(t)
                }
                t = setTimeout(() => {
                    fn();
                }, delay)
            }
        }

 节流与防抖_第4张图片

因此我们需要在改变this的指向,也就是改变参数fn的this的指向

 inp.oninput = debounce(function() {
            console.log(this)//打印this,指向window
        }, 500);

        function debounce(fn, delay) {
            let t = null;
            return function() {
                if (t !== null) {
                    clearTimeout(t)
                }
                t = setTimeout(() => {
                    console.log(this)//指向input
                    fn();//fn的this指向window
                }, delay)
            }
        }

改变this指向后的代码

 inp.oninput = debounce(function() {
            console.log(this.value)        
}, 500);

        function debounce(fn, delay) {
            let t = null;
            return function() {
                if (t !== null) {
                    clearTimeout(t)
                }
                t = setTimeout(() => {
                   
                    fn.call(this);//通过call改变this指向
                }, delay)
            }
        }

节流与防抖_第5张图片

 这样防抖代码优化完了。

完整代码如下:





    
    
    
    Document



    
    


3.节流

什么是节流?

节流:控制高频事件的执行次数(事件频繁触发时,每隔多少秒触发一次)

防抖是只执行最后一次,而节流是减少执行次数。

我们先做一个滚动事件,只要我们让滚动条滚动就会打印123,如下图,我们只是滚动了一下,

就触发了一百多次,如果是和后台服务器产生数据交互,同样对性能消耗是比较大的。

因此我们需要节流。





    
    
    
    Document
    



    


节流与防抖_第6张图片

此时需要节流,来减少执行的次数





    
    
    
    Document
    



    


代码优化后

  window.onscroll = throttle(function() {
            console.log(123);
        }, 500)

        function throttle(fn, delay) {
            let flag = true;
            return function() {
                if (flag) {
                    setTimeout(() => {
                        fn.call(this);
                        flag = true;
                    }, delay)
                }
                flag = false;
            }
        }

你可能感兴趣的:(js,javascript)