为什么nodelist没有forEach?
我正在编写一个简短的脚本来更改<abbr>
元素的内部文本,但发现nodelist
没有forEach
方法。 我知道nodelist
不是从Array
inheritance的,但是看起来不像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;