Reflecting on object properties
# Tom Van Cutsem (12 years ago)
I share your concern (I already got confused when there were just Object.gOPN and Object.keys), but I'm skeptical that we can break the behavior of existing Object.* methods.
You actually forgot Reflect.enumerate, which returns an iterator for all the own and inherited enumerable properties ;-)
Perhaps one easy to remember distinction is that the Object.* methods return arrays whereas the newer Reflect.* methods return iterators (or iterables).
In addition to what Jason just posted about [[OwnPropertyKeys]], I think there are some avoidable inconsistencies in how the various object properties reflection methods are specified. As specified or proposed right now, we have three different such functions: Object.keys, Object.getOwnPropertyNames, and Reflect.ownKeys. Here's their respective behavior:
Object.keys: returns an array of keys of all the iterable own string-keyed properties of the given object
Object.getOwnPropertyNames: returns an array of keys of all the own string-keyed properties of the given object
Reflect.ownKeys: returns an iterator over all the keys of own string- or symbol-keyed properties of the given object
I.e., Reflect.ownKeys behaves more like Object.getOwnPropertyNames, except that it returns an iterator, and returns symbols, too. Under Jason's proposal, it'd at least not return an iterator.
While I see that it's a migration hazard for Object.keys and Object.getOwnPropertyNames to return symbols, too, I think the long-term hazard introduced by the subtle differences between these three methods is of greater concern. There's just no way to tell from their names what the precise behavior will be, and the differences are subtle enough that they'll be hard to remember. For proxies, it's hard to tell which trap has to be implemented to affect the behavior of any one of these methods.
Hence, I think Object.keys and Object.getOwnPropertyNames should return symbols, too. Proxies wouln't need to get a new trap at all. The migration hazard should actually be somewhat mitigated by the fact that many use cases should continue to just work in the face of symbols, while many others should fail fairly obviously. Since I don't have data to base this on, I want to reiterate that the long-term hazard of having three irritatingly similar but different methods is the real argument I'm making.