1

Why

for (i in [1, 2, 3]) console.log(typeof(i), i);

gives this:

[Log] string 0
[Log] string 1
[Log] string 2

I've expected numbers.

@ Safari 7.0 (9537.71), Mac OS X 10.9

akaRem
  • 7,326
  • 4
  • 29
  • 43
  • 1
    JavaScript's `in` keyword is always for keys/properties, not values. [`for-in`](http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.4) iterates keys and the [`in` operator](http://www.ecma-international.org/ecma-262/5.1/#sec-11.8.7) checks for the existence of keys. To get a value, you need to use a [property accessor](http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.1): `arr[i]`. – Jonathan Lonowski Dec 11 '13 at 14:22

2 Answers2

4

Try instead:

var arr = [1, 2, 3];
for (var i in arr)
    console.log(typeof arr[i], arr[i]);

You're getting strings rather than numbers because for..in loops iterate keys/properties (in this case, the Array's indices) rather than values.

To get the value of each key, i, you'll have to use a property accessor, arr[i].


Though, why strings at all rather than the original number indices is because, with current standards, all properties are strings.

console.log(Object.keys( ['foo', 'bar', 'baz'] )); // ["0", "1", "2"]

Any value can actually be used with property accessors, but it'll be converted ToString() before it's actually used as a key/property.

6) Let propertyNameString be ToString(propertyNameValue).

Maps and Symbols are currently planned to be the exceptions to that.


Also, you may find "Why is using “for…in” with array iteration such a bad idea?" of interest and at least consider using a simple for loop instead:

var arr = [1, 2, 3];
for (var i = 0, l = arr.length; i < l; i++)
    console.log(typeof arr[i], arr[i]);

Though, for future reference, the upcoming ECMAScript 6 standard has added for..of loops, which should iterate as you were expecting.

for (var i of [1, 2, 3])
    console.log(typeof i, i); // number, 1, 2, 3
Community
  • 1
  • 1
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
  • The Q was: why strings? Ok, it's easy to guess that I get "indexes" instead of values. But the fact that indexes are strings was very unexpected. Now I understand that it's a "bug by design". .. Thank you for your post, it's well-formed and very useful, but it's not the exact answer for my question. – akaRem Dec 12 '13 at 09:38
  • @akaRem Ah. Sorry. I guess I read it more as: "*why* those *strings*?" I've added an explanation for "*why strings?*" Though, "*bug by design*" is an odd choice of description. I can understand wanting to disagree with the behavior being what it is, but it's still [well-defined and standardized](http://www.ecma-international.org/publications/standards/Ecma-262.htm). So, it's not a "*bug*." – Jonathan Lonowski Dec 12 '13 at 12:10
  • Ok, it's just bad design. :) – akaRem Dec 13 '13 at 14:07
2

That is because an Array in Javascript is a special Object with property keys (which are strings) used as indices. you are iterating that Array like an Object and because of that i is seen as a property key, a string.

To iterate in the right way an Array you have to use the following:

for( var i=0; i < [1,2,3].length; i++){ ... }
MarcoL
  • 9,829
  • 3
  • 37
  • 50