函数节流
背景
javascript中的函数大多数情况下都是由用户主动调用触发的, 除非是函数本身的实现不合理, 否则一般不会遇到跟性能相关的问题,但在少数情况下, 函数的触发不是由用户直接控制的. 在这些场景下, 函数可能被非常频繁调用, 而造成大的性能问题.
场景
window.onresize事件
mousemove事件
scroll滚动事件
共同的特征:高频触发事件函数, 若事件函数里附带DOM相关操作, 会造成非常大的性能消耗.
原理
将即将被执行的函数使用setTimeout延迟一段时间执行, 如果该次延迟执行还没有完成, 则忽略接下来调用该函数的请求.
实现
示例1
underscore.js的函数节流定义: _.throttle(fn, wait, [options]);
_.throttle接收三个参数, 第一次执行默认立刻执行一次fn
@params fn: 需要进行函数节流的函数;
@params wait: 函数执行的时间间隔, 单位是毫秒.
@params options: options有两个选项, 分别是:
{leading: false}: 第一次调用不执行fn
{trailing: false}: 禁止最后一次延迟的调用
_.throttle = function(fn, wait, options) {
var context,
args,
result,
timeout = null,
previous = 0;
if(!options) {
options = {};
}
var later = function() {
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = fn.apply(context, args);
if(!timeout) {
context = args = null;
}
};
return function() {
var now = _.now();
if(!previous && options.leading === false) {
previous = now;
}
var remaining = wait - (now - previous);
context = this;
args = arguments;
if(remaining <= 0 || remaining > wait) {
if(timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = fn.apply(context, args);
if(!timeout) {
context = args = null;
} else if(!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
}
};
};
// demo:
$(window).scroll(_.throttle(function() {
//相关处理
}, 500));
示例2
《javascript设计模式与开发实战》中对函数节流示例:
throttle函数接收两个参数
@params fn: 需要被延迟执行的函数;
@params interval: 延迟执行的时间;
var throttle = function(fn, interval) {
var _self = fn, // 保存需要被延迟执行的函数引用
timer, // 计时器
firstTime = true; // 是否第一次调用
return function() {
var args = arguments,
_this = this;
if(firstTime) { // 如果是第一次调用, 不需要延迟执行
_self.apply(_this, args);
return firstTime = false;
}
if(timer) { // 如果定时器还在, 说明前一次延迟执行还未完成
return false;
}
timer = setTimeout(function() {
clearTimeout(timer);
timer = null;
_self.apply(_this, args);
}, interval || 500);
};
};
// demo:
window.onresize = throttle(function() {
console.log(1);
}, 500);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。