Javascript 为什么节点列表包含未在其长度属性中反映的额外未定义项? 背景:

Javascript 为什么节点列表包含未在其长度属性中反映的额外未定义项? 背景:,javascript,for-loop,nodelist,Javascript,For Loop,Nodelist,在处理节点列表时,我遇到了一个非常奇怪的现象。我想使用getElementsByClassName或类似的东西,然后对它进行排序。我决定一种方法是迭代节点列表,将每个项推送到一个数组中,并对数组进行排序。(顺便说一句,这确实有效,但没有达到预期效果)。我尝试使用for(nodeList中的var I)进行迭代,但它一直在最后几个未定义的项上抛出异常。奇怪的是,我可以使用for(var I=0;I

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

for (var i in document.getElementsByTagName("span"))
    console.count("items");
console.log(document.getElementsByTagName("span").length);
它算出了
项:382项,但长度为
380项。正如所料,当我输入
document.getElementsByTagName(“span”)[380]
document.getElementsByTagName(“span”)[381]
时,它们返回时没有定义。这种奇怪的行为不会发生在数组上(当然,节点列表和数组是不同的,但这确实证明了引起问题的循环并不是不同的)

问题:

为什么
for(nodeList中的var i)
构造在最后返回两个未定义项的nodeList上的行为不同?

迭代语句中的
for捕获的两个附加属性是:

  • 长度
  • 项目
让我给你举个简单的例子。假设页面上有3个SPAN元素

var spans = document.getElementsByTagName( 'span' );
现在,
span
是一个节点列表对象,它包含5属性:

  • 0
  • 一,
  • 二,
  • 长度
  • 项目
前3个属性是索引,它们包含对这些跨度元素的引用。其他两个属性-长度和项目-是两个附加属性。所有节点列表对象都具有这两个属性

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

var i, span;

for ( i = 0; i < spans.length; i++ ) {
    span = spans[i];
    // do stuff with span
}
vari,span;
对于(i=0;i
for in迭代对象的所有可枚举属性,例如长度和项目(这是您的情况)。这是另外两个结果的来源。它还将枚举添加到对象原型中的所有内容


for循环遍历数值索引,不考虑可枚举属性。这就是为什么使用前一种方法更可靠。

节点列表对象类似于数组。因此,不要在
中使用
进行迭代,而是在
中使用
进行迭代。顺便说一句,您可以将节点列表对象转换为规则数组,如下所示:
[].slice.call(NodeList)
。谢谢@Šime Vidas,但为什么会出现这种情况?是什么导致了这种奇怪的行为?
for in
对对象不起作用吗?我在回答中做了解释……再次感谢你,西姆·维达斯。现在这完全有道理了这是有道理的。非常感谢你的解释。现在我知道了,下次再说吧另外,感谢您提供了如何将节点列表转换为数组的代码片段。“这将在未来非常有用。”约瑟夫注意到,尽管我认为这种黑客在IE8中不起作用。我碰巧不在乎IE8,所以我的答案和建议应该一直小心地执行。
:)
lol无论如何我都很感激。XD我一直在寻找这样的小技巧。谢谢你的回答和简洁的定义。