-1

This works:

for (var i = 0; i < this.size(); i++) {
    values.push(this.cards[i].value);
}

but this doesn't:

for (var card in this.cards) {
    values.push(card.value);
}

Why?

Rocket Hazmat
  • 204,503
  • 39
  • 283
  • 323
Big McLargeHuge
  • 11,456
  • 8
  • 64
  • 92
  • 2
    Apparently, `this.size()` is not the same as `this.cards.length`. Any change of seeing the definition for `this`? – Mr Lister Jul 30 '12 at 18:18
  • Is `cards` an array or an object (you shouldn't use `for...in` on arrays). – Rocket Hazmat Jul 30 '12 at 18:18
  • `cards` is an array. From what I understand, `for...in` is acceptable as long as nothing is screwing with the Array prototype. I'm not using any other libraries so... it's okay, right? – Big McLargeHuge Jul 30 '12 at 18:20
  • http://stackoverflow.com/questions/500504/javascript-for-in-with-arrays – Kasapo Jul 30 '12 at 18:21
  • @Kasapo oops, I read that post but not close enough. Specifically, this part of Martijn's comment: "If you want to iterate over an object's keys, use for (var key in object). If you want to iterate over an array’s elements, however, use for(var i = 0; i < array.length; i += 1)" – Big McLargeHuge Jul 30 '12 at 18:22
  • I would say using for...in with arrays is bad practice at best, but I suppose you could do that if not using other libraries... but what if someday you need to add jQuery or something? Also note that any property, including a function, may be added to the array. Look at this post and read answer #1 -- he talks about using for(;;) for arrays vs for..in for objects, which idiomatically makes sense. But if you want to there's nothing to stop you from making your code confusing, prone to conflicts with other code and totaly non-modular :) http://stackoverflow.com/questions/242841 – Kasapo Jul 30 '12 at 18:31
  • Also, cHao's answer is quite informative: "for...in carries with it no connotation of order." – Big McLargeHuge Jul 30 '12 at 18:33

4 Answers4

6

Because in for...in loops, the variable is the key, not the value.

It should be:

for (var card in this.cards) {
    values.push(this.cards[card].value);
}
Rocket Hazmat
  • 204,503
  • 39
  • 283
  • 323
3
for (var card in this.cards) {
    values.push(card.value);
}

... card will be the index number, not the value.

kevin628
  • 3,342
  • 3
  • 23
  • 43
2

The for..in loop enumerates over the property names of an object, not the property values. Should be:

for ( var key in this.cards ) {
    values.push( cards[key].value );
}

One downside of for..in is that it also enumerates over inherited property names (of course, only if the corresponding property is enumerable).


Also, consider this:

var values = this.cards.map(function ( card ) {
    return card.value;
});
Šime Vidas
  • 163,768
  • 59
  • 261
  • 366
1

Because the for (var x in y) syntax loops over PROPERTIES of the object (keys), which can be members of the array if it's an array, but also other enumerable properties.

For example:

var person={fname:"John",lname:"Doe",age:25}; 

for (x in person)
{
  txt=txt + person[x];
}

Will print out all the properties (JohnDoe25), but an array has members that are elements (e.g. the values contained in the array) as well as prototypical properties. Consider this:

// Somewhere deep in your javascript library...
Array.prototype.foo = 1;

// Now you have no idea what the below code will do.
var x, a = [1,2,3,4,5];
for (x in a){
    // Now foo is a part of EVERY array and 
    // will show up here as a value of 'x'
}

x will come up as foo's value at some point in the loop, but that's almost never what would be intended.

I would say don't use for(var x in y) unless you understand what it does -- not trying to be a prick, just save you from a lot of hair-pulling and head-scratching, which I myself went through at one point :/

Kasapo
  • 4,846
  • 1
  • 17
  • 20