如果已经是数组,为什么有必要迭代NodeList?

时间:2015-11-15 23:11:29

标签: javascript arrays

我正在进行一项任务,该任务涉及使用for循环使用以下代码迭代HTML页面上所有按钮标记的NodeList:

var bns = document.getElementsByTagName("button");
for (var i = 0; i < bns.length; i++) {
  bns[i].addEventListener("click", function() {
    alert("you clicked"); 
  });
}

但是,这段代码很有用,我很难理解为什么有必要这样做,即将NodeList放入数组中以便访问它。 NodeList已经是一个数组吗?

1 个答案:

答案 0 :(得分:5)

nodeList是一个类似于数组的对象。它实际上不是一个数组。 ONLY属性的共同点是数组.length和数组索引。它没有任何其他数组方法。

但是,因为它支持数组索引和.length属性,所以您可以使用for循环迭代它,就像使用数组一样。但是,您不能在其上使用.forEach(),因为这是nodeList对象没有的实际数组方法。

您问题中的代码根本不是“将nodeList放入数组中”。它使用nodeList.length访问bns[i]对象的元素以访问nodeList的数字属性。

您可以将nodeList对象想象得更像:

var myNodeList = {
    length: 3,
    "0": domObj1,
    "1": domObj2,
    "2": domObj3
};

在这个类似数组的对象中,你可以这样做:

for (var i = 0; i < myNodeList.length; i++) {
    console.log(myNodeList[i]);
}

即使它实际上不是一个数组。 nodeList实际上是一种主机对象形式,它被赋予了有限的Javascript接口。

仅供参考,有时将nodeList复制到实际数组中 - 当您想要将动态nodeList创建为静态数组时,或者希望能够在其上使用更多Array方法时。这可以这样做:

var bns = document.getElementsByTagName("button");
// copy the nodeList into an actual array
var myArray = Array.prototype.slice.call(bns);

myArray.forEach(function(item) {
    console.log(item);
});

仅供参考,这是MDN关于Why is nodeList not an Array的一个很好的部分。

而且,Array.prototype.slice.call(nodeList)转换需要IE9 +。如果您希望在旧版本的IE中支持,则可以使用垫片here