querySelector()
The DOM can be queried using the.querySelector()
method, which takes an arbitrary CSS selector as an argument:
const myElement = document.querySelector('#foo > div.bar')
This will return the first match (depth first). Conversely, we can check if an element matches a selector:
myElement.matches('div.bar')===true
If we want to get all occurrences, we can use:
const myElements = document.querySelectorAll('.bar')
If we already have a reference to a parent element, we can just query that element’s children instead of the wholedocument
. Having narrowed down the context like this, we can simplify selectors and increase performance.
const myChildElemet = myElement.querySelector('input[type="submit"]')
// Instead of
// document.querySelector('#foo > div.bar input[type="submit"]')
Then why use those other, less convenient methods like.getElementsByTagName()
at all? Well, one important difference is that the result of.querySelector()
isnot live, so when we dynamically add an element that matches a selector, the collection won’t update.
const elements1 = document.querySelectorAll('div')
const elements2 = document.getElementsByTagName('div')
const newElement = document.createElement('div')
document.body.appendChild(newElement)
elements1.length === elements2.length
// false
Another consideration is that such a live collection doesn’t need to have all of the information up front, whereas.querySelectorAll()
immediately gathers everything in a static list, making it less performant.