views:

42

answers:

1

I'm using Google Chrome for this test: Contrary to intuition, the first loop alerts "string" 3 times, while the second loop alerts "number" 3 times.

numarray = [1, 2, 3];

//for-each loop
for(num in numarray) 
    alert(typeof(num));

//standard loop
for(i=0; i<numarray.length; i++) 
    alert(typeof(numarray[i]));

I was expecting both loops to alert "number" 3 times. How is the first loop implemented in Javascript? In other words, if the for-each is syntactic sugar, what is its equivalent using a standard loop?

Also, is there some way to iterate over an object's namespace using a standard loop? I'm looking to touch every one of some object's methods and attributes using a loop of the second kind. I'm new to Javascript and any help is highly appreciated, thanks.

+5  A: 

The reason you're seeing "string" returned in your first loop is that num refers to the array index, not the value of numarray at that index. Try changing your first loop to alert num instead of typeof num and you'll see that it spits out 0, 1, and 2, which are the indicies and not the values of your array.

When you use a for in loop, you're iterating over the properties of an object, which is not exactly equivalent to the for loop in your second example. Arrays in JavaScript are really just objects with sequential numbers as property names. They are treated as strings as far as typeof is concerned.

Edit:

As Matthew points out, you're not guaranteed to get the items in the array in any particular order when using a for in loop, and partly for that reason, it's not recommended to iterate through arrays that way.

filip-fku asks when it would be useful to use for in, given this behavior. One example is when the property names themselves have meaning, which is not really the case with array indicies. For example:

var myName = {
  first: 'Jimmy',
  last: 'Cuadra'
};

for (var prop in myName) {
  console.log(prop + ': ' + myName[prop]);
}

// prints:
// first: Jimmy
// last: Cuadra

It's also worth noting that for in loops will also iterate through properties of the object's prototype chain. For that reason, this is usually how you'd want to construct a for in loop:

for (var prop in obj) {
  if (obj.hasOwnProperty(prop)) {
    // do something
  }
}

This does a check to see if the property was defined by the object itself and not an object it's inheriting from through the prototype chain.

Jimmy Cuadra
There is no guarantee that the array elements will be visited in order. See [for...in](https://developer.mozilla.org/en/core_javascript_1.5_reference/Statements/for...in) at MDC: "iterating over an array may not visit elements in numeric order". This is the main reason for..in is usually not recommended for arrays.
Matthew Flaschen
+1 @Jimmy: Thanks for the explanation.
Senthil
Interesting! Different to what one would expect from C#/Java.. But how is this better than explicitly writing the standard for loop, when all you get are the indices instead of the array values themselves? I.e. why would you ever use this when all you are getting indices anyway? (I guess I can see a use for associative arrays).
filip-fku
+1 @ Matthew - good point.
Jimmy Cuadra
Okay that makes a lot of sense thanks!
Mark
@filip-fku Check my edit for more details.
Jimmy Cuadra
And for the second part, is there any way of getting an array of the property names of an object?
Mark
@Mark - You could loop through the properties with a `for in` loop and push each one to an array. I don't think there's an insta-magic way to do it.
Jimmy Cuadra