title: How can I convert an Array of nodes to a static NodeList?
body: <p><em>NOTE: Before this question is assumed a duplicate, there is a section at the bottom of this question that addresses why a few similar questions do not provide the answer I am looking for.</em></p>
  
  <hr>
  
  <p>We all know that it is easy to convert a NodeList to an Array and there are many ways to do it:</p>
  
  <pre><code>[].slice.call(someNodeList)
  // or
  Array.from(someNodeList)
  // etc...
  </code></pre>
  
  <p>What I am after is the reverse; <strong>how can I convert an array of nodes into a static NodeList?</strong></p>
  
  <hr>
  
  <h1>Why do I want to do this?</h1>
  
  <p>Without getting too deep into things, I am creating a new method to query elements on the page i.e:</p>
  
  <pre><code>Document.prototype.customQueryMethod = function (...args) {...}
  </code></pre>
  
  <p>Trying to stay true to how <code>querySelectorAll</code> works, I want to return a <a href="https://developer.mozilla.org/en-US/docs/Web/API/NodeList" rel="noreferrer">static collection <code>NodeList</code></a> instead of an array.</p>
  
  <hr>
  
  <p>I have approached the problem in three different ways so far:</p>
  
  <h1>Attempt 1:</h1>
  
  <h2>Creating a Document Fragment</h2>
  
  <pre><code>function createNodeList(arrayOfNodes) {
      let fragment = document.createDocumentFragment();
      arrayOfNodes.forEach((node) =&gt; {
          fragment.appendChild(node);
      });
      return fragment.childNodes;
  }
  </code></pre>
  
  <p>While this does return a NodeList, this does not work because calling <code>appendChild</code> removes the node from its current location in the DOM (where it should stay).</p>
  
  <p>Another variation of this involves <code>cloning</code> the nodes and returning the clones. However, now you are returning the cloned nodes, which have no reference to the actual nodes in the DOM.</p>
  
  <hr>
  
  <h1>Attempt 2:</h1>
  
  <h2>Attempting to "mock" the NodeList constructor</h2>
  
  <pre><code>const FakeNodeList = (() =&gt; {
  
      let fragment = document.createDocumentFragment();
      fragment.appendChild(document.createComment('create a nodelist'));
  
      function NodeList(nodes) {
          let scope = this;
          nodes.forEach((node, i) =&gt; {
              scope[i] = node;
          });
      }
  
      NodeList.prototype = ((proto) =&gt; {
          function F() {
          }
  
          F.prototype = proto;
          return new F();
      })(fragment.childNodes);
  
      NodeList.prototype.item = function item(idx) {
          return this[idx] || null;
      };
  
      return NodeList;
  })();
  </code></pre>
  
  <p>And it would be used in the following manner:</p>
  
  <pre><code>let nodeList = new FakeNodeList(nodes);
  
  // The following tests/uses all work
  nodeList instanceOf NodeList // true
  nodeList[0] // would return an element
  nodeList.item(0) // would return an element
  </code></pre>
  
  <p>While this particular approach does not remove the elements from the DOM, it causes other errors, such as when converting it to an array:</p>
  
  <pre><code>let arr = [].slice.call(nodeList);
  // or
  let arr = Array.from(nodeList);
  </code></pre>
  
  <p>Each of the above produces the following error: <code>Uncaught TypeError: Illegal invocation</code></p>
  
  <p>I am also trying to avoid "mimicking" a nodeList with a fake nodelist constructor as I believe that will likely have future unintended consequences.</p>
  
  <hr>
  
  <h1>Attempt 3:</h1>
  
  <h2>Attaching a temporary attribute to elements to re-query them</h2>
  
  <pre><code>function createNodeList(arrayOfNodes) {
      arrayOfNodes.forEach((node) =&gt; {
          node.setAttribute('QUERYME', '');
      });
      let nodeList = document.querySelectorAll('[QUERYME]');
      arrayOfNodes.forEach((node) =&gt; {
          node.removeAttribute('QUERYME');
      });
      return nodeList;
  }
  </code></pre>
  
  <p>This was working well, until I discovered that <strong>it doesn't work for certain elements, like <code>SVG</code>'s</strong>. It will not attach the attribute (although I did only test this in Chrome).</p>
  
  <hr>
  
  <p>It seems this should be an easy thing to do, why can't I use the NodeList constructor to create a NodeList, and why can't I cast an array to a NodeList in a similar fashion that NodeLists are cast to arrays?</p>
  
  <h2>How can I convert an array of nodes to a NodeList, the right way?</h2>
  
  <hr>
  
  <p><strong>Similar questions that have answers that don't work for me:</strong></p>
  
  <p>The following questions are similar to this one. Unfortunately, these questions/answers don't solve my particular problem for the following reasons.</p>
  
  <p><a href="https://stackoverflow.com/questions/24869761/how-can-i-convert-an-array-of-elements-into-a-nodelist">How can I convert an Array of elements into a NodeList?</a> The answer in this question uses a method that clones nodes. This will not work because I need to have access to the original nodes.</p>
  
  <p><a href="https://stackoverflow.com/questions/13351966/create-node-list-from-a-single-node-in-javascript">Create node list from a single node in JavaScript</a> uses the document fragment approach (Attempt 1). The other answers try similar things at Attempts 2, and 3.</p>
  
  <p><a href="https://stackoverflow.com/questions/1776769/creating-a-dom-nodelist">Creating a DOM NodeList</a> is using <code>E4X</code>, and therefore does not apply. And even though it is using that, it still removes the elements from the DOM.</p>