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.