Я объясню ваш код шаг за шагом, если вы хотите увидеть его в codesanbox вот ссылка .
const input = document.querySelector("input");
/*High Order Function
a higher-order function is a function that does at least one of the following:
* takes one or more functions as arguments (i.e. procedural parameters),
* returns a function as its result.
Closure
Here you will see info about that js topic
https://levelup.gitconnected.com/using-closures-in-javascript-to-create-private-variables-c0b358757fe0
*/
// this is a high order function
const debounce = func => {
/* this variable save the setTimeout id and the reason why it
will be persist is because this is the this is a closure and for that,
the returned function will remember their execution context
and therefore the value of timeoutId and calledNTimes*/
let timeoutId;
let calledNTimes = 0;
/* this args parameter comes from the function passed as
argument to debounce, and their value is the event from the addEventListener
function, you can call args as you like but normaly you will
find it with this name.
you use the spread operator to the argument from addEventListener as an
array, because func.apply accept an array of args */
return (...args) => {
console.log((calledNTimes += 1), timeoutId);
console.log("args", args);
/* After the first debounce called, the setTimeout will be
clear while the user is typing, or until it is executed */
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
/* with func apply method you execute the function with
the args comming from the original call, and this args
value is the event from the addEventListener */
func.apply(null, args);
}, 1000);
};
};
const onInput = event => {
fetchData(event.target.value);
};
/* some interesting thing is that as you are executing debounce here
(because you add the parentesis), you can see the second parameter of
addEventListener as the anonymous function returned by debounce, I mean
to say:
(...args) => {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
func.apply(null, args);
}, 1000);
but if you pass literally the function, you will lose the closure feature.
*/
input.addEventListener("input", debounce(onInput));
/* if you console.log the params with and without the spread operator you will
see the difference.*/
function testFunction(...params) {
console.log(params);
}
input.addEventListener("input", testFunction);