From getElementById to querySelectorAll: JavaScript and the DOM

| Comments

This post presents the JavaScript methods for retrieving element nodes from the DOM: getElementById, getElementsByClassName, getElementsByTagName, getElementsByName, querySelector, and querySelectorAll.

JavaScript evolves. The changes spur browsers to become all the better to support it, and developers to figure out how best to apply it. Here, the Selectors API - querySelector and querySelectorAll - is the newer kid on the block. It lets developers pin down elements using CSS selectors.

You can check out browser support for both older and newer methods here. Let’s take a look at each method in turn, starting with the trusty old getElementById

getElementById

If you know the id of the element you want, the document object’s getElementById is the quickest method in your toolbox. It returns a single element (or else null), e.g.:

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="stockings">
  <ul>
    <li class="edible">Orange</li>
    <li class="edible">Chocolate</li>
    <li>Yo-yo</li>
  </ul>

  <ul>
    <li>Harmonica</li>
    <li class="edible">Strawberry bootlaces</li>
    <li><a name="socks">Socks</a></li>
  </ul>
</div>
1
2
// Returns the div and its contents
document.getElementById('stockings');

querySelector

querySelector also returns a single element, but it takes one or more (potentially complicated) CSS selectors, e.g.:

1
2
3
4
5
// Returns the div and its contents (as above)
document.querySelector('#stockings');

// Returns the list element containing 'Harmonica'
document.querySelector('#stockings ul:nth-child(2) li:not(.edible)');

querySelector returns the first matching element it finds; if there is no match, it returns null. You can call it on the document, or on any element, e.g.:

1
2
3
4
5
6
7
8
// Caches second stocking
var stockingB = document.querySelector('#stocking ul:nth-child(2)');

// Returns the list element containing 'Harmonica' (as above)
stockingB.querySelector('li:not(.edible)');

// Returns the list element containing 'Strawberry bootlaces'
stockingB.querySelector('li.edible');

getElementsBy

The getElementsBy… methods each return a live nodeList of elements matching the passed argument, e.g.:

1
2
3
4
5
6
7
8
9
// Returns a nodeList of all the elements with class 'edible'
document.getElementsByClassName('edible');

// Returns a nodeList of uls / stockings
document.getElementsByTagName('ul');

// Returns a nodeList containing the one element with name
// attribute 'socks'
document.getElementsByName('socks');

A live nodeList is an up-to-date collection of elements - an array-like object that updates on the fly (as the DOM changes).

You can call getElementsByClassName and getElementsByTagName on the document, or on any element, whereas getElementsByName is a method of the document only. An empty nodeList is returned if no elements match your query.

querySelectorAll

Like querySelector, querySelectorAll supports multiple selectors (separated by commas), and you can call it on the document, or on any element, e.g.:

1
2
// Returns an array of elements matching the CSS selectors
document.querySelectorAll('li.edible, [name=socks]')

It returns a static nodeList - a snapshot of how things were when the nodeList was created. This means, if the DOM should change, the result of your query may no longer be up-to-date, so you will probably want to re-query the DOM as and when you need to.

querySelectorAll is a little sluggish compared to methods that return a dynamic nodeList but, once you have it, manipulating a static nodeList might be relatively quick (ref). Most of the time, though, nobody will be the wiser if you do trade a little efficiency for more simplicity, e.g.:

1
2
3
4
5
6
7
8
9
10
11
// getElementsByTagName
var items = document.getElementsByTagName('li');
var inedible = [];
for(var i = 0; i < items.length; i+=1) {
  if(items[i].getAttribute('class')!=='edible') {
    inedible.push(items[i]);
  }
}

// vs. querySelectorAll
var inedible = document.querySelectorAll('li:not(.edible)');

Comments