Why do nodelists contain extra undefined items tha

2020-03-26 08:38发布

Background:


I came across a very strange phenomenon while working with a node list. I wanted to use getElementsByClassName or something similar and then sort it. I decided one way would be to iterate through the nodelist and push each item to an array and sort the array. (This did work by the way but not as expected). I tried using the for (var i in nodeList) to iterate through, but it kept throwing an exception on the last few items, which were undefined. the weird part is I could instead use for (var i = 0; i < nodeList.length; i++) to iterate through. I just tested it again and on a stackoverflow page I ran in my console the following code:

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

It counted out to items: 382 but length gave 380. As expected, when I entered document.getElementsByTagName("span")[380] and document.getElementsByTagName("span")[381] they came back undefined. This strange behavior does not occur on arrays (granted, nodeLists and arrays are different, but this does prove that it's not the different for loops causing the issue).

question:


Why does for(var i in nodeList) constructs behave differently on nodeLists returning a couple of undefined items at the end?

2条回答
家丑人穷心不美
2楼-- · 2020-03-26 09:14

The two additional properties that the for in iteration statement catches are:

  • length
  • item

Let me give you a simple example. Let's say that there are 3 SPAN elements on the page.

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

Now, spans is a NodeList object which contains 5 properties:

  • 0
  • 1
  • 2
  • length
  • item

The first 3 properties are indexes and they contain references to those SPAN elements. The other two properties - length and item - are two additional properties. All NodeList objects have these two properties.

The for in statement iterates over all 5 properties of the NodeList object, which is probably not what you want. Therefore, use a regular for statement.

var i, span;

for ( i = 0; i < spans.length; i++ ) {
    span = spans[i];
    // do stuff with span
}
查看更多
啃猪蹄的小仙女
3楼-- · 2020-03-26 09:25

for-in iterates through the all enumerable properties of the object such as length and item (this is your situation). This is where two more results come from. It will also enumerate everything added to object prototype.

for loops through the numeric indeces and doesn't take into consideration enumerable properties. That is why it much more reliable to use former way.

查看更多
登录 后发表回答