Poznajemy closures, czyli domknięcia, i ich największą zaletę, czyli zastosowanie w rekurencji. Już z nich korzystaliśmy. Do dzieła.

Zobaczmy na tę funkcję:

Document.prototype.myGetElementById = function(id) {
    
    var result = null;

    function traverse(node) {
      if(node == null) 
        return;
      if(node.id === id) {
            result = node;
            return;
        }

      for(var child of node.children) 
        traverse(child);
    }

    traverse(this.documentElement); 

    return result;
  }

Zmienna result wykorzystuje domknięcie. Funkcja travese ma do niech dostęp. Oczywiście w języku PHP trzeba by było to dookreślić:

function pseudoCode($id){

   $result = null;

   function traverse($node) use ($result) {
   
   // function body
   
   }

 //(...)

}

Ok, ale po co nam dostęp do result? Można po prostu zwrócić result. Cóż, można. W przypadku jednego elementu, można.

Zobaczmy jednak na tę funkcję:

Document.prototype.myGetElementsByClassname = function(classname) {

    var result = [];
    
    function traverse(node) {

      if(node == null) 
        return;

      if(node.classList.contains(classname)) 
        result.push(node);

      for(var child of node.children) 
        traverse(child);
    }

    traverse(this.documentElement); 

    return result;
  }

Tutaj mamy tablicę. Funkcja rekurencyjna może spokojnie do tej tablicy dopisywać, a funkcja główna tę tablicę zwrócić. Nie trzeba tablicy przekazywać rekurencyjnie w dół a potem w górę mnożąc argumenty funkcji, mnożąc space complexity oraz komplikując logikę.

Domknięcia to bardzo potężny mechanizm.