我会使用underscore.js或lodash源代码来找到这个函数的经过良好测试的版本。
这是下划线代码的略微修改版本,用于删除对 underscore.js 本身的所有引用:
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
function throttle(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : Date.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function() {
var now = Date.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 = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
};
请注意,如果您不需要所有强调支持的选项,则可以简化此代码。
请在下面找到此功能的一个非常简单且不可配置的版本:
function throttle (callback, limit) {
var waiting = false; // Initially, we're not waiting
return function () { // We return a throttled function
if (!waiting) { // If we're not waiting
callback.apply(this, arguments); // Execute users function
waiting = true; // Prevent future invocations
setTimeout(function () { // After a period of time
waiting = false; // And allow future invocations
}, limit);
}
}
}
编辑 1:删除了对下划线的另一个引用,感谢@Zettam 的评论
编辑 2:添加了关于 lodash 和可能的代码简化的建议,感谢 @lolzery @wowzery 的评论
编辑 3:由于流行的请求,我添加了一个非常简单的、不可配置的函数版本,改编自 @vsync 的评论