1

First of all, I'm just a rookie here. I began my JavaScript lessons just a few weeks back via Wrox's "Beginning JavaScript" and so far, so good.

I became curious to why the author never used the for in looping statement to access the different objects in a collection. All the examples used the for statement to traverse along the Collections. So, I gave a shot at an example that traversed through all the link objects but used the for in construct. Here's my code:

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript">
            function linkCounter_onload()
            {
                var linkObj = document.links;
                for(var linkIndex in linkObj)
                {
                    alert(linkObj[linkIndex].href);
                }
            }
        </script>
    </head>
    <body onload="linkCounter_onload()">
        <ul>
            <li><a href="http://news.com">News</a></li>
            <li><a href="http://espn.com">ESPN</a></li>
            <li><a href="http://wikipedia.org">Wikipedia</a></li>
        </ul>
    </body>
</html>

However, when I ran the code by opening the HTML page in Chrome, it first displayed three alert boxes each displaying the href of the respective links and then, it displayed three more alert boxes with the value undefined. I tested the page in IE, and Opera and all three including Chrome behave in the same manner but not Firefox in that it doesn't display the value undefined and there is also an extra alert popup.

If I change the function so that it uses a for loop instead, the code works perfectly. For example:

function linkCounter_onload()
{
   var linkObj = document.links;
   for(var linkIndex = 0; linkIndex < linkObj.length; linkIndex++)
   {
      alert(linkObj[linkIndex].href);
   }
 }

My instinct was to debug the code and see what's happening. I placed a watch on the linkIndex variable in Chrome to see what values it gets. On debugging, I observed that along with the "0", "1" and "2" values, the linkIndex variable also gets some unexpected values like "length", "item" and "namedItem" and then, the loop ends.

After that, I went to Firefox and used the default debugger to watch the linkedIndex variable and along with the above mentioned values, an extra value "@@iterator" was also seen.

Furthermore, I get the the same problem when I try to use for in with other collections.


I've learned that JavaScript can intelligently handle things like Arrays unlike C++ where I need to be careful to make sure that I don't cross the bounds (Not talking about Vectors). This was exciting to me as things were much simpler than C++.

So, why is this happening? Is it because of my misunderstanding of the working of for in construct? If not and if it indeed can traverse through any array, why are there problems when it comes to traversing a collection? Does it have any limitations?

2 Answers 2

1

for...in is best used to enumerate the properties of an object:

var foo = {a:1, b:2, c:3};
for(var varName in foo)
{
    console.log(varName + " : " + foo[varName]);
}

If you run it over an array-like structure:

var arr = [0, 1, 2, 3];
arr.foo = "bar";
for(var x in arr){
    console.log(x + " : " + typeof(x));
}

you'll notice that it enumerates strings, not numbers and pulls out stuff you wouldn't expect. It's really the wrong tool for the job and you should instead:

for(var i = 0; i < arr.length; ++i){
    console.log(i + " : " + arr[i]);
}
Sign up to request clarification or add additional context in comments.

2 Comments

Reading your answer, I find that my current way of learning is too limited. I never knew how to create objects and define properties like the samples you mentioned. So far, I know how to create custom reference types.
My book mentioned using for in to traverse arrays. I thought arrays were a simple linear collection of data but I was wrong. Never knew after creating an array, you can expand it and add properties to it like you just did above. for in will not just go through the array elements but also the properties and methods, right?
0

the for .. in iterates only over enumerable properties structured like this:

var o = {a:1, b:2, c:3};

if you try to alert (linkIndex); you will get

0
1
2
length
item
nameditem

if you console.debug(linkObj); before the loop starts, and open console at Developers Tool (Chrome) you will get

[a, a, a, item: function, namedItem: function]

so?

the array linkObj is not 100% enumerable, and it has some other properties that does not necessarily be a key or index for this array.

thats why first 3 alerts are correct: 0 1 2, but the others are not

Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.