3

背景:


我在处理节点列表时遇到了一个非常奇怪的现象。我想使用 getElementsByClassName 或类似的东西,然后对其进行排序。我决定一种方法是遍历节点列表并将每个项目推送到一个数组并对数组进行排序。(顺便说一句,这确实有效,但不如预期的那样)。我尝试使用for (var i in nodeList)来迭代,但它一直在最后几个未定义的项目上抛出异常。奇怪的是我可以用它for (var i = 0; i < nodeList.length; i++)来迭代。我刚刚再次对其进行了测试,并在我在控制台中运行的 stackoverflow 页面上运行了以下代码:

for (var i in document.getElementsByTagName("span"))
    console.count("items");
console.log(document.getElementsByTagName("span").length);

它算了,items: 382但长度给了380。正如预期的那样,当我进入时document.getElementsByTagName("span")[380]document.getElementsByTagName("span")[381]他们回来时未定义。这种奇怪的行为不会发生在数组上(当然,nodeLists 和数组是不同的,但这确实证明它不是导致问题的不同 for 循环)。

问题:


为什么for(var i in nodeList)结构在 nodeLists 上的行为不同,最后返回了几个未定义的项目?

4

2 回答 2

4

for in迭代语句捕获的另外两个属性是:

  • 长度
  • 物品

让我给你一个简单的例子。假设页面上有 3 个 SPAN 元素。

var spans = document.getElementsByTagName( 'span' );

现在,spans是一个包含5 个属性的NodeList对象:

  • 0
  • 1
  • 2
  • 长度
  • 物品

前 3 个属性是索引,它们包含对这些 SPAN 元素的引用。其他两个属性 - 长度和项目 - 是两个附加属性。所有NodeList对象都具有这两个属性。

for in语句遍历NodeList对象的所有 5 个属性,这可能不是您想要的。因此,请使用常规for语句。

var i, span;

for ( i = 0; i < spans.length; i++ ) {
    span = spans[i];
    // do stuff with span
}
于 2011-09-16T21:47:49.017 回答
2

for-in遍历对象的所有可枚举属性,例如长度和项目(这是您的情况)。这是另外两个结果的来源。它还将枚举添加到对象原型的所有内容。

for循环遍历数字索引并且不考虑可枚举属性。这就是为什么使用前一种方式更可靠的原因。

于 2011-09-16T21:52:47.660 回答