Oi Murillo!
Vou reescrever a função takeUntil para que ela fique um pouco mais legível:
const takeUntil = (times, fn) => {
function segundaFn() {
return times-- > 0 && fn();
}
return segundaFn;
}
Podemos ver então que o return de takeUntil é a segundaFn. Como times e fn foram passados por parâmetro e portanto existem no escopo de takeUntil, a função segundaFn tem acesso a eles.
Vou adicionar uma variável a mais na função takeUntil para que a próxima explicação fique mais entendível:
const takeUntil = (times, fn) => {
let currentCount = times;
function segundaFn() {
return currentCount-- > 0 && fn();
}
return segundaFn;
}
A variável currentCount recebe o valor de times, e tem seu valor diminuido toda vez que segundaFn é executada.
Agora, vamos criar a variável operation que recebe como parâmetros 3 e () => console.log("oi") e chamá-la 4 vezes:
const operation = takeUntil(3, () => console.log("oi"));
operation();
operation();
operation();
operation();
Vamos analisar passo a passo o que acontece:
takeUntil é chamada
currentCount recebe o valor 3
segundaFn é declarada
segundaFn é retornada por takeUntil
operation recebe segundaFn
operation()
- diminui o valor de
currentCount (que vale 2 agora) - printa "oi"
operation()
- diminui o valor de
currentCount (que vale 1 agora) - printa "oi"
operation()
- diminui o valor de
currentCount (que vale 0 agora) - printa "oi"
operation() não faz nada pois currentCount < 0
Observações super hiper importantes:
- executar
operation é a mesma coisa que executar segundaFn currentCount recebe o valor 3 apenas uma vez na chamada de takeUntil. Ou seja, executar operation não atribui o valor de currentCount novamente.
Para confirmar que currentCount recebe o valor apenas uma vez, basta colocar modificar takeUntil para printar o valor inicial da variável
const takeUntil = (times, fn) => {
let currentCount = times;
console.log("valor inicial", currentCount);
function segundaFn() {
return currentCount-- > 0 && fn();
}
return segundaFn;
}
Agora, a mesma sequência de comandos nos tratá o output:
valor inicial: 3
oi
oi
oi
Como esperado, apesar de operation ser chamada várias vezes, "valor inicial 3" foi impresso apenas uma vez.
Se ainda ficar com dúvidas, por favor comente aqui! Espero ter ajudado! :)