• 再谈javascript函数节流


    之前写过但是不记得在哪了,今天同事要一个滑到页面底部加载更多内容的效果,又想起了这玩意儿,确实挺实用和常用的,谨此记之。

    函数节流从字面上的意思就是节约函数的执行次数,其实现的主要思想是通过定时器阻断函数的连续执行,尤其适合用在频繁操作,比如window的resize和scroll事件等。

    window的默认scroll事件间隔时间大概只有十几毫秒,如果频繁的scroll,然后去请求,然后渲染,对性能肯定有很大的影响。

    大概模式:

    var processor = {  
        timer: null,  
     
        performProcessing: function(){  
                // 要执行的代码  
        },  
     
        process: function(){  
            clearTimeout(this.timer);  
            this.timer= setTimeout(function(){  
                processor.performProcessing();  
            }, 100);  
        }  
    };  
     
    //调用  
    processor.process(); 
    performProcessing是要频繁执行的函数,每次process会把之前的定时器timer给清除掉。简单来说,就是performProcessing每次会延迟100ms执行,如果在这段时间内又被执行,每次都会把前面的给clear掉,保证100ms内只会执行一次。
    impress通过闭包实现的函数节流:
    function throttle(fn, delay) {  
        var timer = null;  
        return function () {  
            var context = this, args = arguments;  
            clearTimeout(timer);  
            timer = setTimeout(function () {  
            fn.apply(context, args);  
        }, delay);  
      };  
    } 

    两种方法各有优劣,前一个封装函数的优势在把上下文变量当做函数参数,直接可以定制执行函数的this变量;后一个函数优势在于把延迟时间当做变量。

    举个栗子:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <script type="text/javascript">
            n=0;
            function resizehandler(){
                console.log(++n);
            }
    
            function throttle(method,delay){
                var timer=null;
                return function(){
                    var context=this, args=arguments;
                    clearTimeout(timer);
                    timer=setTimeout(function(){
                        method.apply(context,args);
                    },delay);
                }
            }
            window.onresize=throttle(resizehandler,500);//因为返回函数句柄,不用包装函数了
        </script>
    </body>
    </html>

    函数节流升级版

    var throttleV2 = function(fn, delay, mustRunDelay){
         var timer = null;
         var t_start;
         return function(){
             var context = this, args = arguments, t_curr = +new Date();
             clearTimeout(timer);
             if(!t_start){
                 t_start = t_curr;
             }
             if(t_curr - t_start >= mustRunDelay){
                 fn.apply(context, args);
                 t_start = t_curr;
             }
             else {
                 timer = setTimeout(function(){
                     fn.apply(context, args);
                 }, delay);
             }
         };
     };
    window.onresize = throttleV2(myFunc, 50, 100);

    升级版的作用是myFun间隔50ms执行一次,100ms内必须执行,因为有可能你在50ms内使劲执行myFun,这个时候timer会被clear掉,就会导致事件永远不会执行,这是比较极端的情况。

  • 相关阅读:
    Git删除不存在对应远程分支的本地分支
    Git删除远程分支
    将博客搬至CSDN
    HttpStatus
    Mysql 日期
    jekyll开发静态网站
    修改maven默认的jdk版本
    使用@Value进行静态常量的值注入
    妙笔生花处,惊艳四座
    Integer 和 int 值比较
  • 原文地址:https://www.cnblogs.com/hutuzhu/p/4905004.html
Copyright © 2020-2023  润新知