游戏前端开发教程 前端支付宝支付开发视频教程 前端开发教程书籍
函数节流的出发点,就是让一个函数不要执行得太频繁,减少一些过快的调用来节流。
介绍前,先说下背景。
在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(其核心就是绑定mousemove),甚至一些点击事件(点击的太快);
这些事件有一个特点,在正常的操作中,都有可能在一个短的时间内触发非常多次事件绑定程序。
而大家知道,DOM操作时很消耗性能的,这个时候,如果你为这些事件绑定一些操作DOM节点的操作的话,那就会引发大量的计算;
在用户看来,页面可能就一时间没有响应,这个页面一下子变卡了变慢了。
甚至在IE下,如果你绑定的resize事件进行较多DOM操作,其高频率可能直接就使得浏览器崩溃。
当然我承认有的电脑配置相当的不错,但作为开发者,对性能的优化 还是有必要的……
函数节流
现在简单地来讲一下函数节流:
就是让一个函数无法在很短的时间间隔内连续调用,只有当上一次函数执行后过了你规定的时间间隔,才能进行下一次该函数的调用。
函数节流的原理挺简单的,估计大家都想到了,那就是定时器。
当我触发一个时间时,先setTimout让这个事件延迟一会再执行,如果在这个时间间隔内又触发了事件,那我们就clear掉原来的定时器,再setTimeout一个新的定时器延迟一会执行,就这样。
在《JavaScript高级程序设计》一书有介绍函数节流,里面封装了这样一个函数节流函数:
[code]function throttle(method, context) {
clearTimeout(methor.tId);
method.tId = setTimeout(function(){
method.call(context);
}, 100);
}
//而调用的时候就直接写:
window.onresize = function(){
throttle(myFunc);
}[/code]
这样两次函数调用之间至少间隔100ms,个人不喜欢这种写法,只是一个setTimeout延迟函数,比较原始的节流方法,弊端还是有很多的;
在这个函数升级一下:
[code]var throttle = function(fn, delay){
var timer = null;
return function(){
var context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
fn.apply(context, args);
}, delay);
};
};
//而调用方法为:
window.onresize = throttle(myFunc, 100);[/code]
它使用闭包的方法形成一个私有的作用域来存放定时器变量timer。
两种方法各有优劣,前一个封装函数的优势在把上下文变量当做函数参数,直接可以定制执行函数的this变量;
后一个函数优势在于把延迟时间当做变量(当然,前一个函数很容易做这个拓展),而且个人觉得使用闭包代码结构会更优,且易于拓展定制其他私有变量,
缺点就是虽然使用apply把调用throttle时的this上下文传给执行函数,但毕竟不够灵活。
接下来讨论下怎样拓展深化函数节流:
[code]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);[/code]
则意味着,50ms的间隔内连续触发的调用,后一个调用会把前一个调用的等待处理掉,但每隔100ms至少执行一次。
原理也很简单,打时间tag,一开始记录第一次调用的时间戳,然后每次调用函数都去拿最新的时间跟记录时间比,超出给定的时间就执行一次,更新记录时间。
前端控件开发教程 前端开发教程课本 android开发前端教程
评论前必须登录!
注册