NodeList object is finally an Iterable
Can’t be more excited about the new feature currently available in Chrome Beta (currently 51), which is nothing else but the built-in support for NodeList iteration 🎉
It might be so obvious for people coming from outside the web world that whenever you select a list of UI elements, let’s say this one:
and you want to do some action on each of them, you might expect something like this:
to output this in the console:
but instead what you get is…😤😟
Uncaught TypeError: elements.forEach is not a function
This has been a headache for many web developers a lot of times, since when you get them returned from, for instance, document.querySelectorAll method, what you get back is a collection…
NodeList objects are collections of nodes
Array method lookup
myArray → Array.prototype → Object.prototype → null
NodeList method lookup
myNodeList → NodeList.prototype → Object.prototype → null
The good news is that Chrome has introduced the following changes to NodeList, check it out in the chrome-status page.
Adds `Symbol.iterator` to any DOM interface containing an indexed property getter, and a “length” property.
This means that thanks to the Symbol.iterator, now any object that implements that protocol can be iterated like it was an array. Just open the browser console and type:
you will quickly realize that all of them are iterable objects now.
It also introduces the ability to use the spread operator with NodeList objects:
and the for of statement which invokes a custom iteration hook with statements to be executed for the value of each distinct property:
Workarounds, workarounds, workarounds…
Now let’s go back to the reality for a second..
Probably the most famous one is just “cast” the NodeList into an Array, I say “cast” because what is actually happening is that you are just invoking the slice method with a different context, this will basically just generate a new array instance.
This is also a nice one, Array.from method creates a new Array instance from an array-like or iterable object. The bad news is again current browser support…
This has being considered a bad practice for long time, personally I also don’t like adding new methods to the native objects. But! In this case this is my favourite solution since makes a lot of sense to make NodeList iterables as default and is what you will expect whenever you retrieve items from the DOM.
This might seem like a small thing for most devs but I think it’s actually important that browsers follow this direction, making things behave like developers expect and fixing unexpected behaviours even if they are simple things like this.