Why is there no nodelist?

I worked on a small script to modify the inner text of <abbr> elements, but found that nodelist does not have a forEach method. I know that nodelist does not inherit from Array , but it seems like forEach would be a useful method? Is there any specific problem with the implementation that I don’t know about that does not allow adding forEach to the nodelist ?

Note. I know that Dojo and jQuery have forEach in one form or another for their nodelists. I cannot use either due to limitations.

+72
javascript dom arrays foreach
Nov 17 '12 at 19:05
source share
8 answers

None of these answers explain why NodeList does not inherit from Array, which allows it to have forEach and everyone else.

The answer is found in this thread discussion . In short, it breaks the Internet:

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

An error has occurred in the Google Closure Library, due to which almost all Google applications have failed. The library was updated as soon as it was discovered, but there might still be code that makes the same wrong assumption when combined with concat.

That is, some code did something like

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

However, concat will process "real" arrays (and not instanceof Array) differently than 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 the above code broke when x was a NodeList, because before it went down the doSomethingElseWith(x) path, then after that it went along the otherArray.concat(x) path, which did something- that's weird since x wasn 't a real array.

For some time there has been a proposal for the Elements class, which was a real subclass of Array and was used as the "new NodeList". However, this has been removed from the DOM standard , at least for the time being, since it is not yet possible to implement many technical and technical requirements related reasons.

+65
Nov 19 '14 at 18:25
source share

You can do

 Array.prototype.forEach.call (nodeList, function (node) { // Your code here. } ); 
+39
Mar 14 '14 at 22:07
source share

You can create a new array of nodes.

  var nodeList = document.getElementsByTagName('div'), nodes = Array.prototype.slice.call(nodeList,0); // nodes is an array now. nodes.forEach(function(node){ // do your stuff here. }); 

Note. This is just a list / array of node links that we create here, not duplicate nodes.

  nodes[0] === nodeList[0] // will be true 
+29
Mar 13 '13 at 22:58
source share

In short, his construction conflict implements this method.

From MDN:

Why can't I use forEach or a map in a NodeList?

NodeList are used very much like arrays, and it would be tempting to use the Array.prototype methods. This, however, is not possible.

JavaScript has a prototype-based inheritance mechanism. Array instances inherit array methods (such as forEach or map) because their prototype chain looks like this:

myArray --> Array.prototype --> Object.prototype --> null (The prototype chain of an object can be obtained by calling Object.getPrototypeOf several times)

forEach, map, and the like are native properties of the Array.prototype object.

Unlike arrays, the NodeList prototype chain looks like this:

myNodeList --> NodeList.prototype --> Object.prototype --> null

NodeList.prototype contains the item method, but none of Array.prototype, so they cannot be used in NodeLists.

Source: https://developer.mozilla.org/en-US/docs/DOM/NodeList (scroll down to Why can't I use forEach or a map in NodeList? )

+16
Nov 17 '12 at 19:10
source share

Never say never, this is 2016 and the NodeList object implemented the forEach method in the latest chrome (v52.0.2743.116).

It is too early to use it in production, since another browser does not yet support this (tested by FF 49), but I would suggest that it will be standardized in the near future.

+13
Aug 24 '16 at 21:25
source share

If you want to use forEach in a NodeList, just copy this function from the array:

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

That's all, now you can use it the same as for Array:

 document.querySelectorAll('td').forEach(function(o){ o.innerHTML = 'text'; }); 
+12
May 31 '14 at 18:30
source share

NodeList is part of the DOM API. Look at the ECMAScript bindings, which are also applicable to JavaScript. http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html . The nodeList property and read length property and element (index) return node.

Answer: you need to iterate. There is no alternative. Foreach will not work. I work with Java DOM API bindings and have the same problem.

+1
Nov 17 '12 at 19:14
source share

My decision:

 //foreach for nodeList NodeList.prototype.forEach = Array.prototype.forEach; //foreach for HTML collection(getElementsByClassName etc.) HTMLCollection.prototype.forEach = Array.prototype.forEach; 
+1
Nov 12 '17 at 19:14
source share



All Articles