0

到代码:

<!DOCTYPE html>
<html>
<body>
<p>This.........</p>
<p>That.....</p>
<p>And yet .....</p>
<script>
x=document.getElementsByTagName("p");
for (i in x)  
    document.write("..."+x[i].innerHTML+" "+i+"<br>");
document.write(x.length);
</script>
</body>
</html>

我得到了输出

This.........

That.....

And yet .....
...This......... 0
...That..... 1
...And yet ..... 2
...undefined item
...undefined namedItem
...undefined iterator
...undefined length
3

而不是我所期望的以下内容:

This.........

That.....

And yet .....
...This......... 0
...That..... 1
...And yet ..... 2
3

for-in语句应该在 x 上迭代x长度与x的长度一样多——正如代码本身所说,它是 3——并终止。相反,它似乎正在做的是迭代节点的所有子节点——而不仅仅是document.getElementsByTagName("p")返回的段落标签。

这要么是我在代码中遗漏的一些微妙之处,要么是 JavaScript 引擎中的错误。

这里缺少什么?

4

2 回答 2

7

不要for ... in用于数组和类似数组的东西,比如 NodeList 对象。始终使用数字索引。

for ... in构造用于迭代对象的可枚举属性。严格来说,它甚至不保证数字属性会按数字顺序遍历!使用数字索引,或者将类似数组的对象转换为真实数组并使用.forEach()(在较新的浏览器中):

var x = document.getElementsByTagName("p");
[].slice.call(x, 0).forEach(function(value, index) {
  document.write("..." + value.innerHTML + " " + index + "<br>");
});

编辑— RobG 正确地指出,该.slice()技巧在 IE9 之前的 IE 版本中不起作用。使用带有数字索引的简单for循环来做同样的事情很容易,所以如果您担心 IE8 或更低版本,只需这样做:

var x = document.getElementsByTagName("p");
for (var i = 0; i < x.length; ++i) {
  // whatever with x[i]
}

我认为,真正旧版本的 Mozilla 甚至不支持对 Node 对象使用数组索引。您必须使用该.item( i )方法。然而,我认为这对于现实的新代码来说并不是一个严重的问题。

于 2013-10-30T23:27:18.727 回答
1
var x=document.getElementsByTagName("p");
for(var i=0;i<x.length;i++)
{
  document.write("..."+x[i].innerHTML+" "+i+"<br>");
}
于 2013-10-30T23:27:33.387 回答