2
var myArray = new Array();
var increment = 0;

myArray.push('Tom Hanks', 'Pierce Brosnan', 'Will Smith', 'Richard Ayoade');

for (actor in myArray) {
    console.log(actor + ' is my #' + increment + ' choice.');
    increment++;
}

Something is wrong with this for loop, and I believe its 'actor' in the for-in loop. This prints out a number where the name of the actor should be.

Coming from Ruby, this looks like a .each method iterating over each element in the array, but obviously this is going about things a bit differently. Can anyone explain why this isn't working?

Just picked up JS today. Thanks.

Zack
  • 661
  • 2
  • 11
  • 27
  • 1
    "where the name of the actor should be" --- why do you think so? – zerkms Jul 03 '14 at 01:27
  • because the name of the actor has been pushed into the array, actor has been assigned as the term for the iterator, actor (in my mind) is assigned to each element in the array. However, this is obviously not the case – Zack Jul 03 '14 at 01:28
  • I agree that there are actor strings in the array. But why do you think `for (actor in myArray) {` will put a string value into `actor`? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in – zerkms Jul 03 '14 at 01:30
  • I think I'm thinking too rubyish. As I stated, my thinking on this was similar to the .each method, in which each array element is automatically applied to the iterator term. Is actor in this case the index for each term as opposed to the term itself? – Zack Jul 03 '14 at 01:31
  • 2
    See [Why is using `for…in` on arrays such a bad idea?](http://stackoverflow.com/q/500504/1048572) – Bergi Jul 03 '14 at 01:37

4 Answers4

2

Thats not how for ... in works. From that link:

A for...in loop iterates over the properties of an object in an arbitrary order

And:

for..in should not be used to iterate over an Array where index order is important. Array indexes are just enumerable properties with integer names and are otherwise identical to general Object properties. There is no guarantee that for...in will return the indexes in any particular order and it will return all enumerable properties, including those with non–integer names and those that are inherited.

Given that you are passing in an array the properties are the indexes for the items it holds.

This is why you are getting the index and not the name.

If you want to retain order and print the names, you need a "traditional" for loop, like so:

for (var i = 0; i < myArray.length; i++) {
    console.log(myArray[i] + ' is my #' + (i+1) + ' choice.');
}

The reason to be careful when using for .. in is it can have unexpected results. Checkout this jsFiddle...

var myArray = new Array();
var increment = 0;

myArray.push('Tom Hanks', 'Pierce Brosnan');
myArray.hello = "what?";

for (actor in myArray) {
    alert(actor + ' is my #' + increment + ' choice.');
    increment++;
}

for (var i = 0; i < myArray.length; i++) {
    alert(myArray[i] + ' is my #' + (i+1) + ' choice.');
}

In this example, the first loop will iterate 3 times, picking up the 'hello' property as well as the rest in the array. While the second only does the 2 formal items in the array.

1

In that case, the correct code should be

var myArray = new Array(); var increment = 0;

myArray.push('Tom Hanks', 'Pierce Brosnan', 'Will Smith', 'Richard Ayoade');

for (actor in myArray) {
    console.log(myArray[actor] + ' is my #' + increment + ' choice.');
    increment++; }

it prints out

Tom Hanks is my #0 choice.
Pierce Brosnan is my #1 choice.
Will Smith is my #2 choice.
Richard Ayoade is my #3 choice. 
mcn
  • 711
  • 4
  • 9
1

The simple answer is this: for in loops iterate over properties of an object. An array in JavaScript is an object that's indexed. So, your example is actually this:

Array[4]
0: "Tom Hanks"
1: "Pierce Brosnan"
2: "Will Smith"
3: "Richard Ayoade"
length: 4
__proto__: Array[0]

When you use your for/in code,

for (actor in myArray) {
    console.log(actor + ' is my #' + increment + ' choice.');
    increment++;
}

actor is the property at the time of iteration (0, 1, 2, 3...)

To access the value in your for in loop would require your code to be updated like this:

for (idx in myArray) {
     console.log(myArray[idx] + ' is my #' + idx + ' choice.');
}

However, it's considered bad practice to use for in loops to iterate an array. For example, what if I did something like this:

myArray.type = "Actors";

The console log would return something like:

// 'Actors is my type choice'

Probably not the intended output. Instead, for array iteration, take a look at the for loop or forEach method of arrays.

for (var increment = 0, len = myArray.length; increment < len; increment += 1) {
    console.log(myArray[increment] + ' is my #' + increment + ' choice.');
}

// or...

myArray.forEach(function(actor, increment) {
    console.log(actor + ' is my #' + increment + ' choice.');
});
Jack
  • 9,151
  • 2
  • 32
  • 44
1

You are seeing the index of the array element.

Remember that arrays are objects.

When using for(var item in object), var item is the key(property) associated with the value.

You are accessing the arrays properties(indexes), not values.

You should consider using the Array Objects buitin method forEach.

myArray.forEach(function(actor)){
    console.log(actor + ' is my #' + increment + ' choice.');
    increment++;
});
Gabs00
  • 1,869
  • 1
  • 13
  • 12