Say, I have array with non-numeric indexes:
let arr = [12]
arr["fruit"] = "apple"
arr["off"] = false
for..of does not see non-numeric indexes:for (let item of arr) {
console.log(item)
}
• Output:
12
let iterator = arr[Symbol.iterator]()
let { value, done } = iterator.next()
while (!done) {
console.log(value);
({ value, done } = iterator.next())
}
• Output:
12
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
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
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
Object.getOwnPropertyNames() also sees all non-numeric indexes:for (let prop of Object.getOwnPropertyNames(arr)) {
console.log(prop)
}
• Output:
0 length fruit off
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
}
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]; // Set a variable equal to 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
// Notice how the next 3 lines access properties of the Array, not indexed values?
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.