JS的函数节流与函数去抖

来源:互联网 发布:ibm云计算产品 编辑:程序博客网 时间:2024/06/04 23:25

函数去抖:

先看underscore.js中的实现

function debounce(func, wait, immediate) {    var timeout, result;    return function() {      var context = this, args = arguments;      var later = function() {        timeout = null;        if (!immediate) result = func.apply(context, args);      };      var callNow = immediate && !timeout;      clearTimeout(timeout);      timeout = setTimeout(later, wait);      if (callNow) result = func.apply(context, args);      return result;    };};

在这个函数中,immediate这个参数让我思考了好久,最后终于想明白,究其原因,还是闭包,及函数这块知识不牢靠。

还是在这里记录下,当immediate参数为true的流程记录清楚下:

假如测试的条件如下:给一个input绑定一个keydown事件,触发write函数。

第一次进入,timeout为undefined,则callNow为true,保存result这个函数,并触发函数。OK,假若第二次触发keydow,分为两种情况

假如时间大于wait,setTime函数执行完成,timeout为null,则callNow为true,并触发函数。

假如时间小于wait,setTime函数并未执行完成 ,timeout的值还存在,则callNow为false,不触发函数。如果继续触发,时间依然小于wait,这里需要

注意的是,每次进入函数都会clearTimeout一次。

开始让我费解的地方,主要是result引起的,开始认为result 是一个函数,啊啊 多么可耻的想法,result只是执行的函数的返回结果而已,认为闭包保存result这个函数,

不会发生变化,当小于wait时。

当不设定immediate这个参数时,就简单多了,小于wait甩都不甩的,还每次要重置timeout,如果不触发函数时,就执行函数了。当然这中间最重要的是间隔时间wait,

当时间小于wait,就不会有时间去触发函数而已。


下面就说说这个函数用途:immediate参数为false时,用在事件触发频繁的地方,假如keyup一直触发,每触发一次,cleartimeout一次,一直到wait时间内,都没触发,就执行回调函数了。这个解释太太通俗了。让一个函数在一定间隔内没有被调用时,才开始执行被调用方法。

immediate参数为true时,假如我有个button提交给后台,我按下去,马上提交,继续按下去的时候,只要没到wait时间,就不会提交,防止重复提交的一种方式。

函数节流:

function throttle(func, wait) {var context, args, previous, timeout, result;var later = function() {previous = new Date;timeout = null;result = func.apply(context, args);}return function() {context = this;args = arguments;var now = new Date;var remaining = wait - (now - previous);if (remaining <= 0) { clearTimeout(timeout); timeout = null;previous = now;result = func.apply(context, args);} else if (!timeout) {timeout = setTimeout(later, remaining);}return result;}}


函数节流的流程:

模仿流程,发射子弹,不过这个枪比较老式,只能五秒钟,发射一次,然而有的人,总是不停的扣动扳机。

第一次,扣动扳机,previous为0,remaining显然为负,则timeou为null,previous时间赋值为当前的时间,并发射子弹。

第二次,扣动扳机,假若时间在上一次扣动扳机过去5秒,跟第一次一样,previous为0,remaining显然为负,则timeou为null,previous时间赋值为当前的时间,并发射子弹。这里看出闭包的优越性了。

假若比较心急,只过去1秒,就扣动扳机,remaining的值就为4000,就setTimeout,4秒后,发射子弹,并把previous的值给4秒后的时间,后执行later函数。

这样解释更复杂了,简单来说就是两次间隔时间如果小于wait,由于闭包记录了上一次的执行时间,在wait-(当前时间-上一次时间)后执行函数。

这样就很实用与假如不停的触发函数,我并知道一定的时间内只能发生一次的函数的情况下,使用此种方法。