函数去抖:
先看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-(当前时间-上一次时间)后执行函数。
这样就很实用与假如不停的触发函数,我并知道一定的时间内只能发生一次的函数的情况下,使用此种方法。