The Subtly Different Results of Query Selectors
Tags: javascript, beginners
Published: 2022-07-12 16:43:00

### A Distinctly non-technical introduction 

([Skip To Content](#content))

Recently, I was talking with my instructor about what exactly to blog about. My past experience with blogging was pretty limited and every topic that  crossed my mind seemed either too large or small a problem to address in a single post.

I was grateful then, when Demetrio (my instructor) gave me some solid advice on what to explore: a technical problem you’re struggling to overcome or an idea you don’t understand. 

It’s [no secret](https://fs.blog/feynman-technique/) that writing out concepts in your own words is a great way to make them clear and find out exactly where the holes in your understanding are. By being honest about what problems you’re actually struggling with, you also get a documentation of your learning process which could be invaluable when returning to your posts at later point.

With that in mind, what I’m writing about in this post is a relatively small part of JavaScript that I’ve personally struggled to grasp: the different results of  different query selectors. Those differences are subtle but go into the heart of what a webpage exactly is and how it relates to the code that defines it, so I think blogging about them will be a fantastic exercise for my learning journey.


### Query Selectors <a name="content"></a>



When interacting with the DOM with our JavaScript, we often start by “grabbing” the element we want to affect with a query selector. 

So, for the following stretch of code in an HTML document:

```
    <ul id = list>
      <li class="list-entry">Thing 1</li>
      <li class="list-entry">Thing 2</li>
      <li class="list-entry">Thing 3</li>
    </ul>

```

I could grab the `li` elements in a number of different ways.

Three possible examples are:

- using the `getElementsByClassName()` method

- using the `querySelectorAll()` method

- grab the containing `ul` element and access its `childNodes` property

All of these techniques would allow me to select what I need to on the DOM, but they would also return them to me in subtly different ways.

Using the first method `document.getElementsByClassName('list-entry')` returns an **HTML Collection**:


![returned HTML Collection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swa6jkajmcu3mcjx8jyr.png)

Using the second `document.querySelectorAll(".list-entry")` returns a **static Node List**:


![returned NodeList](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pl3bx1di98aahopilzk.png)


Using the third `document.getElementById('list').childNodes` returns a **live Node List** with a different number of things within:


![returned live node list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zvc9l37zzudg6hbkqw2t.png)


This post is about the differences between these three results, whether those differences are important and whether or not they might affect the way I use each selector.

To begin that process, we'll outline the difference between an Element and a Node.

###Elements and Nodes


Put simply, nodes are the objects that make up the Document Object Model. There are [many different kinds of node](https://www.w3schools.com/jsref/prop_node_nodetype.asp) and  elements are simply one of those kinds that have access to methods that other kinds don't. Not all nodes are elements but all elements are nodes.

![Venn diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/40skkfob61rx3851desg.png)

Having loosely outlined the distinction between these two objects, I want to go into why that distinction is important for understanding the different results of query selectors.

###HTML Collections and Node Lists

The main difference between these two collections is what they can contain:

- HTML Collections contain only elements

- Node Lists can contain any kind of node

This accounts for the different number of objects returned by the `childNodes` property of my `ul` element:

![returned live node list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zvc9l37zzudg6hbkqw2t.png)

and the `document.querySelectorAll()` method:

![returned NodeList](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pl3bx1di98aahopilzk.png)

While the `document.querySelectorAll()` method searched for all nodes with the class name of 'list-item' and returned only the elements I was after, the `childNodes` property returned _all_ of the nodes in contained within my `ul` element which included the non-element nodes such as 'text'.

I can demonstrate that this further by adding a comment to my list:

```
    <ul id = list>
      <li class="list-entry">Thing 1</li>
      <li class="list-entry">Thing 2</li>
      <li class="list-entry">Thing 3</li>
      <!-- Our Comment -->
    </ul>

```

Accessing the `childNodes` property of our `ul` again, I get:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6y5w1x0nxv40bsbq8iu.png)

The number of nodes has changed, whilst the number of elements are exactly the same.

So, when creating a nodeList, for the vast majority of cases I'll only want to handle the elements on my DOM and so the `document.querySelectorAll()` method  on a class is a more precise way to grab the nodes I want.

If I ever want to grab some non-element nodes, I can do so with the `childNodes` property of the containing node.

###-

So, that answers how best to construct a Node List to suit my goals, but what about HTML Collections? Is there a difference between using one of those as opposed to a Node List?

Well, while the nodes contained in both are exactly the same- there is still a difference in the HTML Collection returned by `document.getElementsByClassName()` and the Node List returned by `document.querySelectorAll()`: the HTML Collection is live and the Node List is static.


###Live and Static Collections

The difference between live and static collections is simple enough to state plainly:

- Live collections update their values whenever the DOM is changed

- Static collections often don't unless the method is performed again.


But despite being simple enough to articulate, I personally found it a tricky concept to grasp so, to explore it properly in practice, I'll start a basic DOM manipulation by defining both an HTML Collection and a Node List:

![Defining the two Collections](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pqnwwt1kf3h2r9bia2fc.png)

So far, things are as expected; the two collections have the same number of objects within. 

I'll now add a new element to the DOM with the following:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qmcq63ryvr065sya09cy.png)

If I now recheck the values of my HTMLCollection and nodeList variables, the difference between live and static collections is made clear:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b2z1i2121lk8o3sexe2v.png)


The HTML Collection has automatically updated its containing nodes to include the added `li`, whereas the Node List has not.

If I wanted the Node List to update its contents, I would have to call the `querySelectorAll()` method again.

Knowing this, I can now make the judgement as to which selector would be best to use:

- If I want my collection to be responsive to changes on the DOM, I should create a live HTML Collection

- If I want my collection to change itself _only when redefined_ I should create a static Node List

- Live HTML Collections can be good for web apps that require collections to listen to changing elements on the DOM, but they can also lead to potentially confusing bugs.

- Static Node Lists can be great for knowing exactly what nodes your grabbing and when you want to update your list.

- Live collections are more dynamic, static collections are simpler to use.


### In Closing

I haven't covered everything that separates a Node list from an HTML Collection (there's a difference in the methods that work with each for example), but I feel like I have way more a feeling now on why I would use one selector over another.

Now I’m on the other side of this piece- I also feel like I haven't appreciated how valuable a part of the course these blog posts can be. The clarity this has given me over a funny and precise little part of web-dev has made it something I think I'll return to in a heartbeat for niggly problems I don't quite get.

There’s never a shortage of those.

Thanks for reading, here's to many more!