4

I am calling this on an array with 3 objects in it. It ends up returning the correct keys in addition to these extra keys... unique last truncate random include contains any

Why?

fancy
  • 41,315
  • 56
  • 147
  • 225

2 Answers2

6

You're getting those extra properties because you, or a library you're using, has extended the Array prototype. As Mike points out in his answer, you can skip those by using hasOwnProperty. Indeed, CoffeeScript has an own keyword built in that does this for you:

for own i of foo
  obj = foo[i]
  ...

But, as Mike also points out in his answer, it's more efficient to loop through an array by incrementing a counter rather than iterating over the keys. To do that, you'd use CoffeeScript's for...in syntax:

for obj in foo
  ...

(If you need indices in the loop as well, you can write for obj, i in foo.)

Trevor Burnham
  • 74,631
  • 30
  • 153
  • 193
  • Ahh, great to know, understand it all now. Didn't totally understand CoffeeScripts `in` before. Knowing `for own` is great too. – fancy Aug 16 '11 at 19:36
3

for (... in ...) will return things on the object's prototype. See JavaScript for...in vs for

The best solution is to iterate over array elements using an index loop

for (var i = 0, n = arr.length; i < n; ++i) { ... }

This has the benefit of getting a numeric key instead of a string and reliably iterating in order.

Alternatively, you can use hasOwnProperty to make sure you don't get keys from the prototype.

for (var k in obj) {
  if (!obj.hasOwnProperty(k)) { continue; }
  ...
}

or a variation if you're worried about hasOwnProperty being a overridden.

Even more alternatively, you can define these prototype properties as enumerable: false using Object.defineProperty.

Community
  • 1
  • 1
Mike Samuel
  • 109,453
  • 27
  • 204
  • 234
  • @Mike Probably because your answer is about JavaScript, and the question was about CoffeeScript. (I didn't downvote you, though. Your answer is certainly useful.) – Trevor Burnham Aug 16 '11 at 19:28
  • @Trevor, thanks for the response. CoffeeScript is certainly a separate language, but like most languages that start off compiling to another language early adopters have to understand details of the underlying language -- early adopters of C couldn't use it without understanding a bit of the native instruction set to which it compiled, and early adopters of Scala couldn't get by without knowing about Java or the JVM. – Mike Samuel Aug 16 '11 at 19:32
  • Thanks Mike, useful to understand the underlying concept. My main hiccup was misunderstanding how CoffeeScript implemented `of` and `in` differently. – fancy Aug 16 '11 at 19:38