LOADING

再谈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掉,就会导致事件永远不会执行,这是比较极端的情况。

 

原文链接:https://www.cnblogs.com/hutuzhu/p/4905004.html
本文来源 爱码网,其版权均为 原网址 所有 与本站无关,文章内容系作者个人观点,不代表 本站 对观点赞同或支持。如需转载,请注明文章来源。

© 版权声明

相关文章