21

I've been working on JavaScript lately, and everything was fine until I opened my page in IE11. as per Mozilla website .forEach is supported from IE9.

This is the error I got.

SCRIPT438: Object doesn't support property or method 'forEach'

and this is the code.

var link1 = document.querySelectorAll("nav a");
    var textbox = document.getElementById("OutputWindow");
    link1.forEach(function (element) {
        textbox.innerHTML += "<br/>" + element + "\n";
        element.onclick = function () {
            alert("Hello!");
            console.log("hello!");
            confirm("Hello!");
        };
    });

I tried polyfill, but to my amusement, Array has a forEach in IE11.

Then where I'm going wrong?

PS: This works fine in Chrome.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
Prajwal
  • 3,930
  • 5
  • 24
  • 50
  • Please read [How does accepting an answer work?](http://meta.stackoverflow.com/questions/5234/how-does-accepting-an-answer-work) – Quentin Dec 25 '16 at 13:48
  • @Quentin I cannot accept my own answer within 2-days. Or so the error says. – Prajwal Dec 25 '16 at 13:50
  • So wait a couple of days. Just don't edit the title of the question to include the word "Solved". – Quentin Dec 25 '16 at 13:52

4 Answers4

36

Finally mystery solved.

Apparently, IE9 and above supports Array.forEach but not for NodeList, which querySelector returns. I tried Array.from() to no avail as it requires ES6 or use ES6-shim.

All I had to do was to convert from nodeList to Array, and I did by this.

Array.prototype.slice.call(document.querySelectorAll("nav a"), 0);

as appeared in question In Javascript, what is the best way to convert a NodeList to an array

Community
  • 1
  • 1
Prajwal
  • 3,930
  • 5
  • 24
  • 50
  • And everything "worked" fine in other browsers? That should not be possible. – Teemu Dec 27 '16 at 20:28
  • Hmm... Something seems to have been changed recently. [`document.querySelectorAll`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) used to return a [HTMLCollection](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection) (which doesn't support `forEach`), but currently it returns a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) instead. – Teemu Dec 28 '16 at 05:54
  • 1
    @Teemu yea. It returns `NodeList` and Chrome has `forEach` support for `NodeList` – Prajwal Dec 28 '16 at 05:56
  • Actually, [per standard](https://dom.spec.whatwg.org/#interface-nodelist), it shouldn't ... But the practice says else, hence this is what we're going with from now on. – Teemu Dec 28 '16 at 06:01
6
if (typeof Array.prototype.forEach != 'function') {
Array.prototype.forEach = function (callback) {
    for (var i = 0; i < this.length; i++) {
        callback.apply(this, [this[i], i, this]);
    }
 };
}

if (window.NodeList && !NodeList.prototype.forEach) {
    NodeList.prototype.forEach = Array.prototype.forEach;
 }  
  • 1
    Could you please explain your answer? – Datz Apr 09 '19 at 10:25
  • 2
    Thank you for this code snippet, which might provide some limited, immediate help. A [proper explanation](https://meta.stackexchange.com/q/114762/349538) would greatly improve its long-term value by showing why this is a good solution to the problem and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you’ve made. – Dwhitz Apr 09 '19 at 10:25
4

To avoid changing the code for every forEach() call, here's a polyfill that worked for me. It's simple and recommended within https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach when running forEach() on a NodeList.

if (window.NodeList && !NodeList.prototype.forEach) {
    NodeList.prototype.forEach = Array.prototype.forEach;
}
jg314
  • 586
  • 1
  • 6
  • 15
3

I was doing so:

Array.from(document.querySelectorAll(someElements))

The asnwer for me was simply that:

if (window.NodeList && !NodeList.prototype.forEach) {
   NodeList.prototype.forEach = Array.prototype.forEach;
}

Making sure that forEach also exists in Nodelist.

etiennejcharles
  • 359
  • 2
  • 10