To filter or map nodelists with JavaScript, we can use the spread operator to convert the nodelist to an array. We call document. querySelectorAll to return a nodelist with the p elements. Then we use the spread operator to spread the items in the nodes nodelist into an array.
ES6 - Array Method filter() filter() method creates a new array with all elements that pass the test implemented by the provided function.
map creates a new array by transforming every element in an array individually. filter creates a new array by removing elements that don't belong.
Use the forEach() method to filter a Map in JavaScript. The method gets called with each key-value pair in the Map , where we can check for a condition and use the delete() method to delete any of the Map elements we want to filter out. Copied!
[...nodelist]
will make an array of out of an object if the object is iterable.Array.from(nodelist)
will make an array out of an object if the object is iterable or if the object is array-like (has .length
and numeric props)Your two examples will be identical if NodeList.prototype[Symbol.iterator]
exists, because both cases cover iterables. If your environment has not been configured such that NodeList
is iterable however, your first example will fail, and the second will succeed. Babel
currently does not handle this case properly.
So if your NodeList
is iterable, it is really up to you which you use. I would likely choose on a case-by-case basis. One benefit of Array.from
is that it takes a second argument of a mapping function, whereas the first [...iterable].map(item => item)
would have to create a temporary array, Array.from(iterable, item => item)
would not. If you are not mapping the list however, it does not matter.
TL;DR;
Array.prototype.slice.call(nodelist).filter
The slice() method returns an array.
That returned array is a shallow copy of collection (NodeList)
So it works faster than Array.from()
So it works as fast as Array.from()
Elements of the original collection are copied into the returned array as follows:
Short explanation regarding arguments
Array.prototype.slice(beginIndex, endIndex)
Array.prototype.slice.call(namespace, beginIndex, endIndex)
I found a reference that uses map
directly on the NodeList by
Array.prototype.map.call(nodelist, fn)
I haven't tested it, but it seems plausible that this would be faster because it should access the NodeList directly.
How about this:
// Be evil. Extend the prototype.
if (window.NodeList && !NodeList.prototype.filter) {
NodeList.prototype.filter = Array.prototype.filter;
}
// Use it like you'd expect:
const noClasses = document
.querySelectorAll('div')
.filter(div => div.classList.length === 0)
It's the same approach as mentioned in the MDN docs for NodeList.forEach (under 'Polyfill'), it works for IE11, Edge, Chrome and FF.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With