Why for..of does not see non-numeric array indexes?

Say, I have array with non-numeric indexes:

let arr = [12]
arr["fruit"] = "apple"
arr["off"] = false

1. for..of does not see non-numeric indexes:

for (let item of arr) {
  console.log(item)
}

• Output:

12

2. Iterator does not see non-numeric indexes either:

let iterator = arr[Symbol.iterator]()
let { value, done } = iterator.next()

while (!done) {
  console.log(value);
  ({ value, done } = iterator.next())
}

• Output:

12

However:

3. Object.keys() does see non-numeric indexes:

for (let key of Object.keys(arr)) {
  console.log(`key: ${key}`)
}

• Output:

key: 0
key: fruit
key: off

4. Object.values() sees values of all indexes:

for (let value of Object.values(arr)) {
  console.log(`value: ${value}`)
}

• Output:

value: 12
value: apple
value: false

5. Object.entries() sees all entries:

for (let [key, value] of Object.entries(arr)) {
  console.log(`key = ${key}, value = ${value}`)
}

• Output:

key = 0, value = 12
key = fruit, value = apple  
key = off, value = false  

6. Object.getOwnPropertyNames() also sees all non-numeric indexes:

for (let prop of Object.getOwnPropertyNames(arr)) {
  console.log(prop)
}

• Output:

0
length
fruit
off

7. These non-numeric indexes are enumerable:

let descr

descr = Object.getOwnPropertyDescriptor(arr, "fruit")
console.log(descr)

descr = Object.getOwnPropertyDescriptor(arr, "off")
console.log(descr)

• Output

{
  value: 'apple',   
  writable: true,   
  enumerable: true, 
  configurable: true
}

{
  value: false,   
  writable: true,   
  enumerable: true, 
  configurable: true
}

>Solution :

When you use what you are describing as "non-numeric" indexes with an Array, you are mistaken as to what you are doing.

let arr = [12];     // Create an array with that holds an array with only the number 12 in it
arr["fruit"] = "apple";  // Add a new custom property to your instance of an Array
arr["off"] = false       // Add a new custom property to your instance of an Array

console.log(arr[0]);        // 12
console.log(arr["fruit"]);  // "apple"
console.log(arr["off"]);    // false
console.log(arr.length)     // There is only 1 array item, but 2 additional properties

Arrays only have numeric indexes, but they are objects so they also have properties. For example the Array.length property isn’t something that shows up when you loop over the indexes.

So when you say: "Object.getOwnPropertyNames() also sees all non-numeric indexes", well, no, it doesn’t. As the method name states, it gets all the property names that have been added to that unique instance of the object, not indexes. Index != Property.

If you want names to go with the values, you need to use Object, which has "keys", which can be any string value at all.

Leave a Reply