Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have forEach available on pseudo-arrays returned by querySelectorAll?

Tags:

javascript

dom

Something nice with plain javascript would be to be able to use forEach, map, filter, etc, on the items returned by document.querySelectorAll, document.getElementsBy* etc.

This'd lead to less dependency on jQuery, and simply cleaner code. Right now, this is how we can do it, in an ugly way:

[].forEach.call( document.querySelectorAll(sel), function(el) {
});

This is... verbose.

Any way to be able to use forEach and the likes right away on the elements returned?

like image 276
Florian Margaine Avatar asked Dec 19 '12 17:12

Florian Margaine


1 Answers

A naive way would be to do this if you tested on Chrome:

NodeList.prototype.forEach = Array.prototype.forEach;

This works. On Webkit. It doesn't on Firefox though. Because FF returns an HTMLCollection...

The most cross-browser way I've found:

NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach;

It doesn't work on IE8 and lower though, because they choke when adding properties to host objects prototypes.

Full list:

NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach;
NodeList.prototype.map = HTMLCollection.prototype.map = Array.prototype.map;
NodeList.prototype.filter = HTMLCollection.prototype.filter = Array.prototype.filter;
NodeList.prototype.reduce = HTMLCollection.prototype.reduce = Array.prototype.reduce;
NodeList.prototype.reduceRight = HTMLCollection.prototype.reduceRight = Array.prototype.reduceRight;
NodeList.prototype.every = HTMLCollection.prototype.every = Array.prototype.every;
NodeList.prototype.some = HTMLCollection.prototype.some = Array.prototype.some;

Or, to please our dear Bergi (and also because it is cleaner):

['forEach', 'map', 'filter', 'reduce', 'reduceRight', 'every', 'some'].forEach(
    function(p) {
    NodeList.prototype[p] = HTMLCollection.prototype[p] = Array.prototype[p];
});

Considering the link to perfectionkills, it's mostly irrelevant there. The problem is that the DOM is mostly not behaving the same on browsers when extended. This modification is sane in all the browsers except IE <=8.

like image 127
Florian Margaine Avatar answered Oct 06 '22 01:10

Florian Margaine