yui 3 中的卡喉函数模块
[javascript]
YUI.add("yui-throttle", function(Y) {
/* Based on work by Simon Willison: http://gist.github.com/292562 */
var throttle = function(fn, ms) {
ms = (ms) ? ms : (Y.config.throttleTime || 150);
if (ms === -1) {
return (function() {
fn.apply(null, arguments);
});
}
var last = (new Date()).getTime();
return (function() {
var now = (new Date()).getTime();
if (now - last > ms) {
last = now;
fn.apply(null, arguments);
}
});
};
Y.throttle = throttle;
}, "3.1.1", {
requires : [ "yui-base" ]
});
[/javascript]
以上是这个所谓卡喉函数模板的源程序,从YUI把它做为基本模块安装在返回对象上,可以看出YUI非常青睐这个函数,可能一般情况下没什么用处,但如果你想控制一个函数的执行间隔时间,这个函数的亮点也就出来了。比如window.resize这个函数,你在改变浏览器窗口大小的时候它就被不停的执行着,很多时候我们只需要在resize结束之后执行一下就行了,当然还有其它用处。。。。等等你的发掘。下面我们来通过一个实例,演示一下这个函数如何卡喉。
//没有进行卡喉处理的函数
window.onresize = function(){
console.log('hello');
}
//进行的卡喉处理的函数
window.onresize = YUI().throttle(function(){
console.log('hello');
},3000)
通过演示比较你就可以看到,
没有经过处理的resize函数在你改变窗口大小时不停执行很多次[我是通过拉动firebug面板来改变窗口大小从而激发窗口的resize函数],
经过卡喉处理的函数通过比较上一次到下一次执行的间隔时间来限制它是否执行,从而减少了它的执行次数。这样一来resize就达到了减速效果,
这样看,YUI叫它为 throttle [掐脖子,扼杀 n.节流阀] 非常的形象,我做个假设就好比一个人正常情况每分呼吸50次,如果被一个人掐着脖子限制你5秒种呼吸一次,这样一样你一分钟也只能呼吸 12 次了,呵呵,这样就达到了throttle效果,节流嘛。。。如此而已。
最后让我们一窥它的实现原理,
看代码
var throttle = function(fn, ms) {skipped...}
我们看到它有两个参数,第一个参数 fn 就是要被卡喉的函数,第二个参数 ms 是限制执行间隔时间,以毫秒为单位,默认是150毫秒,如果设置为 -1 就不节流,相当于没有效果,和没有使用一样只是兜了个圈子,让我们看看它如何兜一圈。
if (ms === -1) {
return (function() {
fn.apply(null, arguments);
});
}
如果 (ms === -1) 返回一个匿名函数,匿名函数内部 fn.apply(null,arguments);这句只是起到执行作用,不要被apply蒙蔽了。apply只是在执行的过程中可以切换执行体而已,当然它还有继承的功能,内容超过本篇之外,这里不解释了。
再往下看,var last = (new Date()).getTime(); 定义一个 last 做为最后一次执行时间,
函数内部
return (function() {
var now = (new Date()).getTime();
if (now - last > ms) {
last = now;
fn.apply(null, arguments);
}
});
var now = (new Date()).getTime(); 定义一个 now 做为当前执行时间, (now - last > ms) 这句的说如果当前时间减去一次执行时间要是大于设定间隔时间就通过 fn.apply(null, arguments) 执行被卡喉函数,而且把当前时间设定为最后一 次执行时间,为下一次比较做准备,这次执行就被这么扼杀了。两个变量的比较就是这个卡喉函数的核心。到此这个所谓的卡喉扼杀函数就说完了。