debounce
debounce copied to clipboard
Optimized version
Hello! Thanks for your nice and clean debounce function. Lodash's is powerful but overly complicated for most use. I optimized your code and also wrote it for ES6.
- You only need timeout to be outside the returned closure. The rest of the vars can go inside.
- You can use Date.now() instead of new Date().
- You don't need to save the context for the func.apply(), you can just pass null.
- You can use a ternary to return an IIFE which returns nothing to set the timeout variable to undefined.
ES5
var debounce = function(wait, func) {
var timeout;
return function() {
var last,
args = [].slice.call(arguments, 0),
timestamp = Date.now(),
later = function() {
last = Date.now() - timestamp,
timeout = wait > last ? setTimeout(later, wait - last) : function() { func.apply(null, args); }();
};
timeout || (timeout = setTimeout(later, wait));
}
};
In ES6, you can use the ...args operator instead of [].slice.call().
const debounce = (wait, func) => {
var timeout;
return (...args) => {
var last,
timestamp = Date.now(),
later = () => {
last = Date.now() - timestamp;
timeout = wait > last ? setTimeout(later, wait - last) : (() => { func.apply(null, args); })();
};
timeout || (timeout = setTimeout(later, wait));
}
};
I liked your optimized version, but it does not work. You have to move the timestamp (and args) up in the closure.
function debounceOpt(func: (...args: any[]) => void, wait: number) {
var timeout, stampTest;
return function () {
var last;
var args = [].slice.call(arguments, 0);
var timestamp = stampTest = Date.now();
var later = function () {
console.log(timestamp - stampTest); // never 0
last = Date.now() - stampTest, // This works, timestamp doesn't
timeout = wait > last ? setTimeout(later, wait - last) : function () { func.apply(null, args); }();
};
timeout || (timeout = setTimeout(later, wait));
}
};
I ended up with this:
function debounceOpt(func, wait) {
var timeout, timestamp, args;
function later() {
var last = Date.now() - timestamp;
console.log(last);
timeout = wait > last ? setTimeout(later, wait - last) : (func.apply(null, args), null);
};
return function () {
args = [].slice.call(arguments, 0);
timestamp = Date.now();
timeout || (timeout = setTimeout(later, wait));
}
};