我知道 Undercore.js 中的
debounce
返回一个函数,该函数将推迟执行直到等待时间结束。
我的问题是,与普通 Javascript 中的常规
debounce
函数相比,使用 setTimeout
是否有优势?它们的作用不一样吗?
它们非常不同,并且用于完全不同的情况。
_.debounce
返回 function
,setTimeout
返回 id
,您可以使用它来取消超时。无论您调用_.debounce返回的函数多少次,它在给定的时间范围内只会运行一次。
var log_once = _.debounce(log, 5000);
function log() {
console.log('prints');
}
log_once();
log_once();
log_once();
log_once();
log_once();
var id = setTimeout(function() {
console.log('hello');
}, 3000);
clearTimeout(id);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
的文章,其中包括 underscore 在其实现中使用的源代码:
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
debounce 函数充当您想要调用的实际函数的生成器,这样状态就可以保留在闭包内部,如下所示:
// example function
let sayHello = (name) => console.log(`Hi ${name}`)
// generate a debounced version with a min time between calls of 2 seconds
let sayHelloDebounced = debounce(sayHello, 2000)
// call however you want
sayHelloDebounced('David')
堆栈片段中的演示
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
let sayHello = (name) => console.log(`Hi ${name}`)
let sayHelloDebounced = debounce(sayHello, 2000)
sayHelloDebounced('David')
sayHelloDebounced('David')
sayHelloDebounced('David')
其他实现
在正式英语中,debounce 的作用与 setTimeout 和clearTiemout 的作用相同。 如果您不想使用 debounce,您可以将 setTimeout 与clearTiemout 一起使用来实现相同的行为。
let timer;
function setTimer(){
clearTimeout(timer);
timer = setTimeout(() => console.log("here"), 1000);
};
setTimer();
setTimer();
setTimer();
setTimer();
// here
[![enter image description here][1]][1]