Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
(document.querySelectorAll('*')).forEach ?
var els = document.querySelectorAll('a');
els.forEach(function(e){console.log(e.href);}); // TypeError: els.forEach is not a function
// Why?
// document.querySelectorAll returns a NodeList.
// First thing first, as opposed to other NodeList, this one is not live, mostly because the
// implementation of a live object would be terribly complicated for some selectors
// NodeList are a DOM interface introduced in DOM core level 1 (random guess)
// The ECMAScript binding (http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html) defines
// NodeList as objects. Unfortunately, the spec is not very accurate in how this object should be
// implemented. It does not say if things are inherited or not, no word on NodeList.prototype
// The de-facto standard is apparently that the protoype chain looks roughly like:
// myNodeList -> NodeList.prototype -> Object.prototype
// As you can notice, Array.prototype is not here. It has to be noted that at the time NodeList were
// invented + standardized was before/at the time of ECMAScript 3.
// At this time, Array.prototype only had:
// .concat, .join, .pop, .push, .reverse, .shift, .slice, .sort, .splice, .unshift
// Most of these methods are not applicable to NodeList since they either write on the NodeList.
// .forEach, .filter, etc. came later on with ECMAScript 5 but it was too late to consider adding
// Array.prototype on the prototype chain (is it really too late?)
// A workaround: on FF4 and Chrome, I have been able to have the following running:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<style>
html, body {
margin:0;
padding:0;
}
td {
width:100px;
height:100px;
background-color:purple;
}
</style>
<script type="text/javascript">
NodeList.prototype.forEach = Array.prototype.forEach;
HTMLCollection.prototype.forEach = Array.prototype.forEach; // Because of https://bugzilla.mozilla.org/show_bug.cgi?id=14869
function randomColorString(){
var r, g, b;
r = Math.floor(256*Math.random()).toString(10);
g = Math.floor(256*Math.random()).toString(10);
b = Math.floor(256*Math.random()).toString(10);
return ('rgb('+ r +','+ g +','+ b +')');
}
function createTable(row, col){
var t = document.createElement('table');
var r,c;
var i,j;
for(i=0 ; i<row; i++){
r = document.createElement('tr');
for(j=0; j<col ; j++){
c = document.createElement('td');
r.appendChild(c);
}
t.appendChild(r);
}
return t;
}
function windowLoad(){
var table = createTable(6, 10);
document.body.appendChild(table);
var cells = document.getElementsByTagName('td');
cells.forEach(function(e,i,a){
e.style.backgroundColor = randomColorString();
});
}
window.addEventListener("load", windowLoad, false);
</script>
<title> TITLE </title>
</head>
<body>
</body>
</html>
// THE END !
// ... wait a minute
// Apparently, this doesn't work with document.querySelectorAll on FF4. I'll have to dig into that.
// THE END (until progress is made in the direction of DOM ECMAScript binding?)
@milgner

This comment has been minimized.

Show comment Hide comment
@milgner

milgner Feb 28, 2012

Ha, this is brilliant in its simplicity! Thank you very much! I was just starting to tear my hair because the result from a querySelectorAll() call didn't support forEach.

milgner commented Feb 28, 2012

Ha, this is brilliant in its simplicity! Thank you very much! I was just starting to tear my hair because the result from a querySelectorAll() call didn't support forEach.

@DavidBruant

This comment has been minimized.

Show comment Hide comment
@DavidBruant

DavidBruant Feb 28, 2012

Actually, now, I would have a completely different advice which is to turn every NodeCollection/HTMLCollection to an actuall array.
Something like:
function $$(selector){
return Array.prototype.slice.call(document.querySelectorAll(selector), 0);
}

Owner

DavidBruant commented Feb 28, 2012

Actually, now, I would have a completely different advice which is to turn every NodeCollection/HTMLCollection to an actuall array.
Something like:
function $$(selector){
return Array.prototype.slice.call(document.querySelectorAll(selector), 0);
}

@milgner

This comment has been minimized.

Show comment Hide comment
@milgner

milgner Feb 28, 2012

Thanks for the feedback. I'll keep that in mind but currently a forEach method is all I need.

milgner commented Feb 28, 2012

Thanks for the feedback. I'll keep that in mind but currently a forEach method is all I need.

@issam-chouchane

This comment has been minimized.

Show comment Hide comment
@issam-chouchane

issam-chouchane Jan 5, 2015

Try

    var querycollection = WinJS.Utilities.query(".className_1", document);
    querycollection.forEach(function (e) {
        // do some stuff with 'e'
        consol.log(e);
    });

Try

    var querycollection = WinJS.Utilities.query(".className_1", document);
    querycollection.forEach(function (e) {
        // do some stuff with 'e'
        consol.log(e);
    });
@dima734

This comment has been minimized.

Show comment Hide comment
@dima734

dima734 Sep 15, 2016

I use

[].forEach.call( querycollection, function(element_value, index_key){
console.log(element_value);
} );

But i'm looking for some library, maybe someone knows more perfect way to fix with library? Does Array.prototype.slice.call() work for every browser?

dima734 commented Sep 15, 2016

I use

[].forEach.call( querycollection, function(element_value, index_key){
console.log(element_value);
} );

But i'm looking for some library, maybe someone knows more perfect way to fix with library? Does Array.prototype.slice.call() work for every browser?

@daniville1

This comment has been minimized.

Show comment Hide comment
@daniville1

daniville1 Oct 13, 2016

I have modified and used this:

(function() {
    if (typeof NodeList.prototype.forEach === "undefined") {
        NodeList.prototype.forEach = Array.prototype.forEach;
    }

    if (typeof HTMLCollection.prototype.forEach === "undefined") {
        HTMLCollection.prototype.forEach = Array.prototype.forEach;
    }
})();

thank you!!

I have modified and used this:

(function() {
    if (typeof NodeList.prototype.forEach === "undefined") {
        NodeList.prototype.forEach = Array.prototype.forEach;
    }

    if (typeof HTMLCollection.prototype.forEach === "undefined") {
        HTMLCollection.prototype.forEach = Array.prototype.forEach;
    }
})();

thank you!!

@vinyll

This comment has been minimized.

Show comment Hide comment
@vinyll

vinyll Jan 31, 2018

Or you could use Array.from(document.querySelectorAll('a'))

vinyll commented Jan 31, 2018

Or you could use Array.from(document.querySelectorAll('a'))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment