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.