4

I was using for...in loops to log values, and I noticed that the variable in a for...in loop (i, in this case) is a string.

for (var i in ['a', 'b', 'c']) {
  console.log(i, typeof i)
}

I searched the ECMAScript specifications, in the section titled "The for-in, for-of, and for-await-of Statements", for any information on this, but could not find anything on this.

My question is, is there anything in the spec about this, and if not, why is it a string?

shreyasm-dev
  • 2,711
  • 5
  • 16
  • 34
  • `i` is what you put in it!? You have an array of string, so `i` is going to be assign a string. If you do `for (var i in [1, 2, 3])` then `i` is going to be a integer. – Dominique Fortin Sep 05 '20 at 03:40
  • 1
    @DominiqueFortin I don't think the type of the array has anything to do with it. Maybe you're thinking of for...of loops? – shreyasm-dev Sep 05 '20 at 03:41
  • `i` is not the array, it will be assign an element of the array. – Dominique Fortin Sep 05 '20 at 03:43
  • @DominiqueFortin I know that, I just don't understand this - "You have an array of string, so `i` is going to be assign a string" - Why? – shreyasm-dev Sep 05 '20 at 03:44
  • This is an oversimplification, but it will help you understand. `for (var i in [1,2,3]) {}` is equivalent to `var arr = [1,2,3]; for(var z = 0; z < arr.length; ++z) {var i = arr[z]; ... }`. – Dominique Fortin Sep 05 '20 at 03:52

1 Answers1

6

for..in calls EnumerateObjectProperties, which does:

Return an Iterator object (26.1.1.2) whose next method iterates over all the String-valued keys of enumerable properties of O. The iterator object is never directly accessible to ECMAScript code. The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.

All object properties are either strings or symbols. Even properties on arrays which can be set and retrieved as if they were numbers are interpreted as strings (and retrieved as strings when retrieved via for..in or other property enumeration methods like Object.keys or Object.getOwnPropertyNames). You can also see [[OwnPropertyKeys]](), which says:

The Type of each element of the returned List is either String or Symbol.

For example, with Array.prototype.push, you can see:

5. For each element E of items, do:
  a. Perform ? Set(O, ! ToString(len), E, true).

Property assignment always results in setting a property which is either a string or a symbol. (See isPropertyKey - If Type(argument) is String, return true. If Type(argument) is Symbol, return true. Otherwise Return false.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • 1
    Is it safe to say that the reason Symbol keys aren't enumerated by `for..in` is that it predates `Symbol` or is there another reason? I used to know... – Aluan Haddad Sep 05 '20 at 03:44
  • 2
    That sounds likely - if an object was iterated over with `for..in` code written in 2013 which does not understand Symbols, it could throw errors, so perhaps symbols are omitted so as not to break backwards compatibility. – CertainPerformance Sep 05 '20 at 03:46