Uczymy się pisać polyfill dla wbudowanej funkcji JavaScript querySelectorAll. Do dzieła.

Jeżeli czegoś nie przerobiliśmy, to przypomnijmy sobie tematy takie jak:

  • Element.match
  • Rekurencja
  • DOM Traversal
  • Dopisywanie funkcji do prototypu

Oto nasz polyfill isMatch:

function isMatch(node, selector) {
    if(node.matches) { 
      return node.matches(selector);
    } else { 
      
      var matches = Element.prototype.matchesSelector || 
        Element.prototype.mozMatchesSelector ||
        Element.prototype.msMatchesSelector || 
        Element.prototype.oMatchesSelector || 
        Element.prototype.webkitMatchesSelector;
      return matches.call(node, selector);
    }
  }

Idziemy po drzewie DOM, do results dopisując te elemnty, które robią match na selektorze:

  Document.prototype.myQuerySelectorAll = function(selector) {
    var result = [];
    
    function traverse(node) {
      if(node == null) 
        return;
      if(isMatch(node, selector)) 
        result.push(node);
      for(var child of node.children) 
        traverse(child);
    }

    traverse(this.documentElement); 
    return result;
  }

Funkcja rekurencyjna jest wewnątrz, base case to null (element bez dzieci będzie mieć null pod children), najpierw sprawdzamy rodzica, potem rekurencyjnie jego dzieci.

Dopisane do prototypu Document, więc documentElement mamy pod this.