0

Can someone explain to me why lastEventTimestamp isn't reset to null each time a function is called?

Function.prototype.throttle = function (milliseconds, context) {
    var baseFunction = this,
        lastEventTimestamp = null,
        limit = milliseconds;

    return function () {
        var self = context || this,
            args = arguments,
            now = Date.now();

        if (!lastEventTimestamp || now - lastEventTimestamp >= limit) {
            lastEventTimestamp = now;
            baseFunction.apply(self, args);
        }
    };
};
S. Ballard
  • 13
  • 2
  • 1
    *a function is called*: which function? Please show the code that produces the result you did not expect? – trincot Mar 18 '17 at 19:47

1 Answers1

0

When you call throttle a new closure is created in which lastEventTimestamp is defined as null. The inner function has a reference to that variable, so when that function is returned, the closure still has a reference to it, and keeps its state:

function test() {
}

var myTest = test.throttle(100);

myTest();
myTest();

When you then call the function myTest -- that was returned -- repeatedly, it will act on the same instance of that lastEventTimestamp variable. Note that calling that function will not execute the assignment lastEventTimestamp = null, but only the code in that inner function body. So indeed there is no reason why that variable should be reset. It keeps its state between calls. This is the power of closures in JavaScript.

See which console.log calls are executed in this snippet:

Function.prototype.throttle = function (milliseconds, context) {
    console.log('initialising throttle');
    var baseFunction = this,
        lastEventTimestamp = null,
        limit = milliseconds;

    return function () {
        console.log('running throttle wrapper function');
        var self = context || this,
            args = arguments,
            now = Date.now();

        if (!lastEventTimestamp || now - lastEventTimestamp >= limit) {
            lastEventTimestamp = now;
            console.log('calling original function');
            baseFunction.apply(self, args);
        }
    };
};

function test() {
    console.log('running test');
}

var myTest = test.throttle(100);

myTest();
myTest(); // runs too soon, so test is not called.

Note how 'running throttle wrapper function' only appears once in the output.

Community
  • 1
  • 1
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thank you very much, that link you included helped a lot, especially Example 7. My lack of knowledge about closures had lead to my confusion. Thanks again! – S. Ballard Mar 18 '17 at 21:03