Snakes and Coffee Snakes and Coffee - 4 months ago 14
Javascript Question

Why doesn't nodelist have forEach?

I was working on a short script to change

<abbr>
elements' inner text, but found that
nodelist
does not have a
forEach
method. I know that
nodelist
doesn't inherit from
Array
, but doesn't it seem like
forEach
would be a useful method to have? Is there a particular implementation issue I am not aware of that prevents adding
forEach
to
nodelist
?

Note: I am aware that Dojo and jQuery both have
forEach
in some form for their nodelists. I cannot use either due to limitations.

Answer

None of these answers explain why NodeList doesn't inherit from Array, thus allowing it to have forEach and all the rest.

The answer is found on this es-discuss thread. In short, it breaks the web:

The problem was code that incorrectly assumed instanceof to mean that the instance was an Array in combination with Array.prototype.concat.

There was a bug in Google's Closure Library which caused almost all Google's apps to fail due to this. The library was updated as soon as this was found but there might still be code out there that makes the same incorrect assumption in combination with concat.

That is, some code did something like

if (x instanceof Array) {
  otherArray.concat(x);
} else {
  doSomethingElseWith(x);
}

However, concat will treat "real" arrays (not instanceof Array) differently from other objects:

[1, 2, 3].concat([4, 5, 6]) // [1, 2, 3, 4, 5, 6]
[1, 2, 3].concat(4) // [1, 2, 3, 4]

so that means that the above code broke when x was a NodeList, because before it went down the doSomethingElseWith(x) path, whereas afterward it went down the otherArray.concat(x) path, which did something weird since x wasn't a real array.

Fortunately, there is hope. The DOM standard now includes an Elements class that is a real subclass of array. This isn't implemented anywhere yet (largely because ES6 subclassing isn't implemented anywhere yet). But when it is, we'll finally have a good alternative to NodeList.

Comments