Performance - document.getElementById vs document.querySelector

Intro

The introduction of the document.querySelector and document.querySelectorAll functions was a welcome response to jQuery’s use of CSS selectors to select elements. Although there are many developers that still prefer jQuery’s shortened syntax and extended functionality, library and application authors utilize these functions.

Tests

Helper Function

  function createDiv(id){
    let el = document.createElement("div");
    el.id = id;
    document.body.appendChild(el);
  }

Using document.getElementById

  let totals = [];
  for(let i = 0; i < 10000; i++){
      let id = "id-" + i;
      createDiv(id);
      id = "#" + id;
      let t0 = performance.now();
      let el = document.getElementById(id);
      let t1 = performance.now();
      totals.push(t1 - t0);
  }
  let sum = totals.reduce((s, t)=> s+t, 0);
  let avg = sum / totals.length;
  console.log(sum, avg);

Using document.querySelector

  let totals = [];
  for(let i = 0; i < 10000; i++){
      let id = "id-" + i;
      createDiv(id);
      let t0 = performance.now();
      let el = document.querySelector(id);
      let t1 = performance.now();
      totals.push(t1 - t0);
  }
  let sum = totals.reduce((s, t)=> s+t, 0);
  let avg = sum / totals.length;
  console.log(sum, avg);

Results

Method Chrome Firefox
getElementById 0.00071750 ms 0.00099799 ms
querySelector 0.03854850 ms 0.14990900 ms

Analysis

Unsurprisingly, document.querySelector performs worse, but that has to be due to the added functionality. What if we checked it ourselves and passed it to document.getElementById?

Using document.getElementById with test for selector

  let totals = [];
  for(let i = 0; i < 10000; i++){
      let id = "id-" + i;
      createDiv(id);
      id = "#" + id;
      let t0 = performance.now();
      if(id.charAt(0) === "#"){
          let el = document.getElementById(id.substr(1));
      }
      let t1 = performance.now();
      totals.push(t1 - t0);
  }
  let sum = totals.reduce((s, t)=> s+t, 0);
  let avg = sum / totals.length;
  console.log(sum, avg);

This test in Chrome returned a result of 0.0006940000000025975 ms. That is faster than the document.getElementById result above, but it clearly falls within a margin for error. It appears to be faster to manually test for the number sign (#), split the string, and use document.getElementById than to use the document.querySelector without the test. Perhaps a custom function would be faster in broader use cases.

You may also like