JavaScript: Handle NodeList objects as an array

Ivan Stevkovski
wearelaika
Published in
3 min readDec 3, 2019

If you’ve ever used document.querySelectorAll(targetElement) then you’ve been hit with the childNodes property. The first mistake many developers make when handling a collection of nodes is thinking they are receiving back an array and try to handle it as such.

This of course does not work because the return value you receive is actually a NodeList object containing the child nodes of the target element and therefore cannot be handled as an array.

So the question is..

How do I handle these child elements as an array?

Well, you can! You will, however, need to convert the NodeList object to an array by using one of the multiple solutions to achieve it.

  1. Use Array.from method
  2. Use Array.prototype.slice
  3. Use ES6 spread operator

Let’s build a scenario! Say you are building a feature on your site that autoloads the next post as you scroll and you want to handle the element that is currently inside the viewport.

This feature needs to be dynamic and self-sustaining, so the biggest question is, out of all currently loaded posts, how can you differentiate which one is currently inside the viewport?

Let’s set our goals:

  1. Grab all of the posts
  2. Convert all of the posts into an array
  3. Filter the post that is inside the viewport

Method 1 — Array.from

const postsCollection = document.querySelectorAll(‘.post’);
const postsCollectionArray = Array.from(postsCollection);

Method 2 — Array.prototype.slice

const postsCollection = document.querySelectorAll(‘.post’);
const postsCollectionArray = Array.prototype.slice.call(postsCollection);

Method 3 — ES6 spread operator

const postsCollectionArray = […document.querySelectorAll(‘.post’)];

Personally I favor using ES6 methods or newer over anything else. That being said, I will continue the scenario using Method 3. The next step is to filter the post inside the viewport and we’re done!

Now that you have an array of elements it’s very important to use the most efficient method to handle it, so we need to use a method that will stop and return a value the first time the criteria is satisfied. This method is Array.prototype.find()

Additionally, we will need a function that will check if the provided element is inside the viewport:

// Check if element is in viewport
const isElementInViewport = el => {
const scroll = window.scrollY || window.pageYOffset;
const boundsTop = el.getBoundingClientRect().top + scroll;

const viewport = {
top: scroll,
bottom: scroll + window.innerHeight
};

const bounds = {
top: boundsTop,
bottom: boundsTop + el.clientHeight
};
return ((bounds.bottom >= viewport.top && bounds.bottom <=
viewport.bottom) || (bounds.top <= viewport.bottom &&
bounds.top >= viewport.top));
};

Now that we have all of the necessary functions and handlers in place we just need to filter the element.

const viewportElement = [...document.querySelectorAll('.post')].find(el => {
if (isElementInViewport(el)) return el;
});

That’s all there is to it! You’ve successfully handled the posts and filtered the one inside the viewport!

--

--

Ivan Stevkovski
wearelaika

I am a passionate Front-end Developer who strives to design and build modern dynamic and api-powered websites and web applications using the latest standards.