为什么nodelist没有forEach?

我正在编写一个简短的脚本来更改<abbr>元素的内部文本,但发现nodelist没有forEach方法。 我知道nodelist不是从Arrayinheritance的,但是看起来不像forEach会是一个有用的方法呢? 有没有一个特定的实现问题,我不知道,防止添加forEach nodelist

注意:我知道Dojo和jQuery都以某种forms为每个节点列表提供了forEach 。 由于限制,我不能使用。

这些答案都没有解释为什么 NodeList不从Arrayinheritance,因此允许它有forEach和所有其余的。

答案在这个es讨论线程中find 。 总之,它打破了networking:

问题是错误地假设instanceof的代码,意味着该实例是Array和Array.prototype.concat的组合。

Google的Closure Library中存在一个错误,导致几乎所有的Google应用程序都因此而失败。 这个库一旦被find就立即更新,但是可能还有代码与concat组合使用相同的错误假设。

也就是说,一些代码做了类似的事情

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

但是, concat会将“真实”数组(不是instanceof数组)与其他对象区别开来:

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

所以这意味着上面的代码在x是NodeList的时候破坏了,因为在它到达doSomethingElseWith(x)path之前,而之后它沿着otherArray.concat(x)path走,这做了奇怪的事情,因为x不是真正的数组。

有一段时间,有一个关于一个Elements类的提议,它是Array的一个真正的子类,并将被用作“新的NodeList”。 但是, 从DOM标准中删除了这个标准 ,至less现在是这样,因为由于各种技术和规范相关的原因而不能实现。

你可以做

 Array.prototype.forEach.call (nodeList, function (node) { // Your code here. } ); 

您可以考虑创build一个新的节点arrays。

  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. }); 

注意:这只是我们在这里创build的节点引用的列表/数组,没有重复的节点。

  nodes[0] === nodeList[0] // will be true 

简而言之,其实施该方法的devise冲突。

来自MDN:

为什么我不能使用forEach或在NodeList上映射?

NodeList和数组非常类似,使用Array.prototype方法会很诱人。 但是,这是不可能的。

JavaScript有一个基于原型的inheritance机制。 数组实例inheritance了数组方法(例如forEach或map),因为它们的原型链如下所示:

myArray --> Array.prototype --> Object.prototype --> null (一个对象的原型链可以通过调用Object.getPrototypeOf来获得)

forEach,map和类似的是Array.prototype对象的属性。

与数组不同,NodeList原型链如下所示:

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

NodeList.prototype包含item方法,但不包含Array.prototype方法,所以它们不能在NodeLists上使用。

来源: https : //developer.mozilla.org/en-US/docs/DOM/NodeList (向下滚动到为什么我不能使用forEach或在NodeList上映射?

永远不要说从不,2016年,而且NodeList对象在最新的chrome(v52.0.2743.116)中实现了forEach方法。

现在在生产中使用它还为时尚早,因为其他浏览器还不支持这个function(经过testing的FF 49),但是我猜想这个标准很快就会被标准化。

如果你想在NodeList上使用forEach,只需从Array复制该函数:

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

那就是所有的,现在你可以像使用Array一样使用它:

 document.querySelectorAll('td').forEach(function(o){ o.innerHTML = 'text'; }); 

NodeList是DOM API的一部分。 看看也适用于JavaScript的ECMAScript绑定。 http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html 。 nodeList和一个只读长度属性和item(index)函数来返回一个节点。

答案是,你必须迭代。 没有替代。 Foreach将无法工作。 我使用Java DOM API绑定,并有相同的问题。

我的解决scheme

 //foreach for nodeList NodeList.prototype.forEach = Array.prototype.forEach; //foreach for HTML collection(getElementsByClassName etc.) HTMLCollection.prototype.forEach = Array.prototype.forEach;