Pierwszy wzorzec rekurencyjny w JS jaki poznamy to nazwany IIFE z wywołaniem rekurencyjnym opatrzonym warunkiem. Zaczynajmy.
Rzecz pierwsza – warunek następnego wywołania:
function printNumbers(curr, max){
console.log(curr++);
if(curr <= max)
printNumbers(curr, max);
}
printNumbers(1,5)
//1
//2
//3
//4
//5
Taki warunek znajduje się przed wywołaniem rekurencyjnym. Przydaje się w funkcjach, które coś robią, niekoniecznie coś zwracają, bo takie mają w zwyczaju mieć warunki bazowe na samej górze.
Rzecz druga, IIFE:
(function (){
console.log("hello world!");
})();
//hello world
Takie funkcje wywołują się od razu. Mogą też przyjmować argumenty:
(function (name){
console.log("hello " + name);
})("John");
//hello John
Mogą też być nazwane. Jedyny powód, aby były to po to, by zapewnić możliwość rekurencyjnego wywoływania:
(function printNumbers(curr, max){
console.log(curr++);
if(curr <= max)
printNumbers(curr, max);
})(1,5);
//1
//2
//3
//4
//5
Teraz przykład znaleziony w internecie:
(function domTraversal(parentElement){
parentElement.childNodes.forEach((element) => {
if(element.innerText && element.className === 'change'){
element.innerText = `${element.innerText} changed`
}
if(element.hasChildNodes()){
domTraversal(element);
}
});
})(document.querySelector('body'))
Czyli:
- Funkcja uruchamiana od razu, jako IIFE musi mieć nazwę jeżeli ma być wykonana rekurencja
- Zaczyna od złapania dzieci body i przechodzi w forEach
- Wewnątrz forEach nie jest w stanie wyskoczyć returnem ani też nie ma takiej potrzeby
- Bierze się za pracę nad pierwszym elementem
- Jeżeli element ma dzieci (warunek przed wywołaniem rekurencyjnym) to wywołuje się na nich
- Jeżeli zostały jeszcze jakieś elementy dla pętli forEach to kontynuuje prace na nich i ewentualnie ich dzieciach.