To the code:
<!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>
i'm getting the output
This.........
That.....
And yet .....
...This......... 0
...That..... 1
...And yet ..... 2
...undefined item
...undefined namedItem
...undefined iterator
...undefined length
3
rather than the following which is what i expect:
This.........
That.....
And yet .....
...This......... 0
...That..... 1
...And yet ..... 2
3
the for-in statement is supposed to iterate on x as many times as the length of x-- which is 3 as the code itself is saying-- and terminate. what it seems to be doing instead is iterating on all the children of the node-- not just the paragraph tags returned by document.getElementsByTagName("p").
this is either some subtlety i'm missing in the code, or a mistake in the JavaScript engine.
What's missing here?
2 Answers 2
Don't use for ... in for arrays and array-like things like NodeList objects. Always use a numeric index.
The for ... in construct is for iterating through the enumerable properties of an object. Strictly speaking, it doesn't even guarantee that the numeric properties will be traversed in numeric order! Use a numeric index, or else convert array-like objects to real arrays and use .forEach() (in newer browsers):
var x = document.getElementsByTagName("p");
[].slice.call(x, 0).forEach(function(value, index) {
document.write("..." + value.innerHTML + " " + index + "<br>");
});
edit — RobG points out correctly that the .slice() trick won't work in IE versions before IE9. It's easy enough to do the same thing with a simple for loop with a numeric index, so if you're worried about IE8 or below, just do that:
var x = document.getElementsByTagName("p");
for (var i = 0; i < x.length; ++i) {
// whatever with x[i]
}
Really old versions of Mozilla, I think, didn't even support using array indexing with Node objects; you had to use the .item( i ) method. I don't think that's a serious concern for realistic new code however.
7 Comments
var x=document.getElementsByTagName("p");
for(var i=0;i<x.length;i++)
{
document.write("..."+x[i].innerHTML+" "+i+"<br>");
}
1 Comment
; after i++ made an error, sorry. just edited.
forloop.for..infor iterating arrays or sequences.for..initerates properties (which includes array indexes, but also other properties likeitemanditerator).the for-in statement is supposed to iterate on x as many times as the length of x- Wrong. That is not what thefor ... instatement means at all. It iterates over the keys ofx.