你的位置:首页 > Java教程

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