Reputation: 67
Given a debounce function as below:
const debounce = (fn, delay) => {
let timer;
return () => {
if(timer) clearTimeout(timer);
timer = setTimeout(fn, delay)
}
}
document.getElementById("mybutton").addEventListener('click', debounce(()=>console.log("Clicked"),1000))
Every time the button is triggered, it makes a call to the "debounce" function, my question is how could the "timer" variable not being re-initialized? As far as I'm aware, the "let" keyword scope is block-scoped, then how could the "timer" hold the setTimeOut identification from the last call?
Every comment is appreciated, thank you.
Upvotes: 1
Views: 4227
Reputation: 1074178
Every time the button is triggered, it makes a call to the "debounce" function...
No, it's only called once — when you add the event handler. The code .addEventListener('click', debounce(()=>console.log("Clicked"),1000))
calls debounce
and passes its return value into addEventListener
, exactly the way foo(bar())
calls bar
and passes its return value into foo
. The return value of debounce
is a function; that function is what's passed to addEventListener
and so that function is what gets called each time the event occurs, not debounce
.
That's why there's only one timer
variable, because there's only one call to debounce
. The function it returns closes over the variable.
In comments you've asked for a bit of clarification:
Just another related question, when the "debounce" returns the inner function, which gets passed onto the "addEventListener", does the returned function stay the same after another couple more 'click' event?
Yes. It's one function. This code:
document.getElementById("mybutton").addEventListener('click', debounce(()=>console.log("Clicked"),1000));
is exactly the same as this code, other than that this code has an identifier the code above doesn't:
const eventHandlerFunction = debounce(()=>console.log("Clicked"),1000);
document.getElementById("mybutton").addEventListener('click', eventHandlerFunction);
Another saying for the question is: does the execution context of the returned function not being re-created every time the button is clicked
The execution context for the call to debounce
is only created once, when you call debounce
. That execution context contains the timer
variable. The context (and thus the variable) are retained as long as something has a reference to them. The function debounce
creates (eventHandlerFunction
in the code above) has a reference to them, so they exist as long as that function exists.
(Because the "denounce" function execution is already gone after the first button click, the "timer" variable isn't there anymore after the first button click I should say.)?
The timer
variable continues to exist as long as the eventHandlerFunction
continues to exist. That function will continue to exist until all references to it are released — in this case, either by removing it from the element's click
event handler list, or when the element itself goes away.
Upvotes: 5