Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimized version #2

Open
stevensacks opened this issue Jun 27, 2016 · 1 comment
Open

Optimized version #2

stevensacks opened this issue Jun 27, 2016 · 1 comment

Comments

@stevensacks
Copy link

stevensacks commented Jun 27, 2016

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.

  1. You only need timeout to be outside the returned closure. The rest of the vars can go inside.
  2. You can use Date.now() instead of new Date().
  3. You don't need to save the context for the func.apply(), you can just pass null.
  4. 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));
    }
};

@kritollm
Copy link

kritollm commented Dec 5, 2020

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));
    }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants