Convert NodeList to Array
Now that most browsers have implemented querySelectorAll, the native selectorEngine, many framework-dependent developers are getting a rude awakening when dealing with the result of QSA calls: the NodeList object. NodeLists are array-like but don't feature many of the methods provided by the Array, like forEach
, map
, filter
, etc. JavaScript does, however, provide a very simple way to convert NodeLists to Arrays:
var nodesArray = Array.prototype.slice.call(document.querySelectorAll("div"));
The result of the code above is a true Array object containing all of the nodes returned by the QSA. You could even make the code shorter with this alternative:
var nodesArray = [].slice.call(document.querySelectorAll("div"));
Both snippets will give you an Array for which you can iterate over and do all those other awesome array things!
It's no secret that Facebook has become a major traffic driver for all types of websites. Nowadays even large corporations steer consumers toward their Facebook pages instead of the corporate websites directly. And of course there are Facebook "Like" and "Recommend" widgets on every website. One...
David asked me if I'd be up for a guest post picking out some of my favorite Pens from CodePen. A daunting task! There are so many! I managed to pick a few though that have blown me away over the past few months. If you...
I recently stumbled upon David DeSandro's website when I saw a tweet stating that someone had stolen/hotlinked his website design and code, and he decided to do the only logical thing to retaliate: use some simple JavaScript goodness to inject unicorns into their page.
The Dojo Toolkit seems to just get better and better. One of the new additions in Dojo 1.6 was the use of LESS CSS to create Dijit themes. The move to using LESS is a brilliant one because it makes creating your own Dijit theme...
David does the second example not create a new object allocation that would require being garbage collected? I’d say it’s only a good method for start-up tasks but nothing that is running often, running in a loop or animation.
Hmm… Time to use stuff like underscore js perhaps?
Also, you can really simply iterate over a node list with native JS anyways.
Or, as per my suggestion, use some underscore:
It’s never a good idea to use
for...in
to cycle through indexed collections. It’s way slower than the classic for:But the whole point of having an Array instead of a
NodeList
is to get all those goodies likemap
andforEach
, as stated in the post. Callbacks are slow, but if you care about performances, then don't use for…in.Doesnt work on old IEs. Though it’s less and less relevant
IE8 still will be relevant for the next couple of years.
Is there a difference in performance using this vs
Array.prototype.slice.call(nodelist)
It seems the latter would be slightly more performant, as I thought an array literal allocated memory, and the above doesn’t.
Yes, indeed, using Array.prototype is slightly faster… but takes longer to type!
It’s just that. A good garbage collector will free the memory right after the statement.
If performances aren’t vital, you can go for [].
Why are we using
Array.prototype.slice
……. And not simplyArray.slice
…?Because it doesn’t work that way?
In my opinion, using a raw
[]
un-intuitive and code-smelly. It doesn’t clearly communicate the intent of the code unless the developer reading it happens to have read a blog post saying “Hey, typing [] is shorter than typing Array.prototype”. And since when is shorter superior? I don’t think you should sacrifice any semantic meaning for the sake of wiggling your fingers a little less. The time you save by typing[]
is completely insignificant compared to the potential time you make the next person waste trying to figure out your cool shortcuts.Array.prototype.slice
preserves the meaning of the code and it’s google-able. And if you really are a slow typist, how aboutconst slice = Array.prototype.slice;
? How often are you really typing this, anyways?If you’re curious about performance have a look at the jsperf test Convert Nodelist to Array
Here’s the compact code (102 bytes) that allows not only a global , but also a local QSA (to find all the descendants of a certain element)
Note: I tried to use
[].concat
just like[].slice
which will work appropriately with arrays but not aNodeList
.[].concat
concats the elements of the passed array and does not create another dimension in the returned array which is what I was getting with a NodeList and was causing my error. So do not confuseNodeLists
with Arrays.With Babel, life gets even a bit easier:
or for single use stuff, inline all the stuffs:
This probably works on Babel, but please don’t do that or advice others to do that. NodeList doesn’t have the Iterator symbol, and thus it can’t work with the standard. If you run your code in latest Chrome for example, it will throw an error of
. The fact that it works on Babel, doesn’t mean it is correct.
[...document.querySelectorAll("button")]
works perfectly for me in chromeHow to get the value of this array? Since I follow yours what I get is the object instead of value.
Why not just use ES6?
Why not use
Array.apply
?