Abi Travers

My Blog. Full Stack Software Engineer. Ex-Growth Hacker.

Live Element Lists vs Static Ones, Why document.getElementsByClassName is different to document.querySelector(‘.className’) : Bitesize JS

Bitesize Javascript series

I was working on a bug in our code base with a colleague, when he noticed something strange about the behaviour of document.getElementsByClassName.

In our code base it had been implemented as if it acted like document.querySelector, ie. you could save a list of elements to a variable, then mess with those elements parent, but the variable will still contain all those elements as they were when you set it.

When you call document.getElementsByClassName a HTMLCollection is returned. This list is a LIVE list*.

When you call document.querySelector a NodeList is returned. This is NOT a live list but is instead a STATIC list* (ie. it should not change).

const a = document.querySelectorAll(‘.list-of-child-elements’)
const b = document.getElementsByClassName(‘list-of-child-elements’)

At this point the two lists look pretty similar.

Now let us select the parent element to the child elements with the class name ‘list-of-child-elements’.

const x = document.getElementsByID('parent-wrapper')
<div id="parent-wrapper"> ... </div>

Ok so lets do something to this parent element, this is the element which contains that child elements.

<div class="list-of-child-elements">...</div>

Here we have cloned one of the child elements, by getting the first element in the list of child elements and cloning it with .cloneNode(true). Then we have appended this as a child to the parent element.

If we look in the HTML at this point there will be a new div under the parent element ‘parent-wrapper’ exactly the same as one of it’s children ‘list-of-child-elements’.

Now when we go into the console we see the difference between the static and live lists:

HTMLCollection(2)[div.list-of-child-elements, div.list-of-child-elements]

The list which was created by .getElementsByClassName has been updated so that it is correct as of the new DOM model. The list which was created by .querySelectorAll is the same as when it was first set to the variable, so when the DOM was originally used to query the html.

*N.B. Neither of these are arrays of elements but instead html collections or node lists. While they may look like elements, to actually make them arrays you need to call Array.prototype.slice.call(collection/nodeList), on them to make them a proper array**.

**Javascript technically does not have arrays but instead objects which behave almost identically to arrays.

Document.documentElement: BiteSize JS and web performance

I was recently advised to use Document.documentElement when querying the DOM to get the html element.

This came about because I was refactoring an old code base to swop JQuery for vanilla JS. Doing this I saw:


This is JQueries way of selecting the whole Html element.

Since I am relatively new to javascript I was about to use the generic querySelector*.




When a colleague told me this was bad for performance.

Document.querySelector is basically a search / find operation. It scans the whole document to find the given element then selects that one and holds it in memory.

To save the browser searching through the whole document, document.documentElement returns the root element of the document.

The root element is the sole parent element to all the other elements. The top level element.

In a Html document the <html> </html>.

This means that when the JS runtime environment executes the Document.documentElement it knows exactly where to go and doesn’t waste any time searching the whole DOM.

*I have since been told that there is a better way to query the DOM in terms of performance.

Events, EventListeners and their relation to JavaScript, the Browser and the DOM


Notes on things I have learnt about events and their listeners and JS while working through Wes Bos’s JS30 and talking to colleague at Compare the market.

(Beware this is not a coherent article just random scribbles which i took down through a conversation).

Events/ Events/ Events

The DOM Is an event based system.

The Browser is an event based system.

Keydown etc are events which happen that the browser can capture / listen to and note.

When the browser is open and JS script is listening for a particular event it can then go off and execute a given task.

The DOM can execute events.

The browser DOM is an event based system … idea is that everything is responding to some sort of event.

Lots of events and responses.

Allows the programme to not only observe what is happening but do something about the events that are happening.

Javascript can tap into and listen to browser events.

JS is the base language which has been plugged into the browser.

JS is embedded in the browser .. Just as assembly language is embedded in the comp.. It is the only language the browser and the DOM is implemented on.

Event Listener

An event listener is an object that implements the EventListener interface, which defines a single method named handleEvent(). An event listener is used to observe a specific event and perform one or more actions when it occurs.

interface EventListener {

        void handleEvent(in Event evt);


handleEvent: function(event) {

       // Do something here, possibly using the event parameter


To add an event listener we have to employ the addEventListener() method.

This then listens for a specific event which happens in the browser/ on the DOM and does something with it. These elements can be attached to ‘targets’(see below) so elements within the DOM.


window.addEventListener(‘keydown’, playSound);

 function playSound(e) {

         const audio = document.querySelector(`audio`);



Examples of events

‘Transitionend’ which happens when CSS has the transition property, is an event, like many others, which is only found in the browser environment.

So if you press the D key .. If the browser is open it listened to that event, notes it… then the eventListener can trigger an action.

After DOM is loaded it fires an event called DOM content loaded .. If you attach a listener to this event you know when it fully loaded.

Tracking is just attaching events to stuff …. So click through rate is just a function attached to an event in the DOM.

Can create custom events .. Which is a combination of actions .. So when these actions happen do this event.

There are extra APIS which are environment dependant..

There are APIS you are going to see in the browser that you don’t see in the Node.

Transitionend is an event which is an API..

APIs in the sense that they are things that belong to the browser … so if you run js in node then you don’t see transitionend etc ..

Node is still an event based system so has it’s own events it can run.

..one of the reasons it is different from other languages.

ALL TRACKING TECHNOLOGY we have is based off JS events. … custom tag management.

Event Target

The event target is the element (div, span etc) that generates or dispatches the current event

So if you click on a div, that div becomes the event target for the click event that occurred

Threading and Sync/ Async

Javascript is Single threaded means everything runs on one thread.

Single thread — it does one thing at one time.

There are some situations that make it look like it is doing more than one thing at a time but just a tick.. Ie. SetTimeOut

async javascript event handlers

SetTimeOut with a time of 0 means that the function gets plopped on the event loop … 0 seconds means do this at any point when you are free .. If you are busy ignore it, put it in the loop then call it later. .. It’s not there yet .. It will be there at some point in time.

learning javascript eventloop

Single threaded is naturally sync.