Object.keys VS Object.getOwnPropertyNames

# Jürg Lehni (15 years ago)

I am aware that these function names are probably set in stone by now, but am curious to hear the reasons for their naming, as there seem to be many discrepancies in there, mostly:

  • The use of both 'key' and 'name' for the same thing
  • The omitting of 'get' in Object.keys

In terms of a clean API, something along these lines would have seemed more consistent:

Object.getKeys Object.getOwnKeys

As I am new to the community process of EcmaScript but strongly involved with the language for soon 10 years through projects like Scriptographer.org and Helma.org, and therefore concerned with the language's future, I am curious to find out more about these processes of the defining of the language's API and syntax.

Jürg

# Dmitry A. Soshnikov (15 years ago)

Hello Jürg,

Sunday, April 18, 2010, 6:35:50 PM, you wrote:

I am aware that these function names are probably set in stone by now, but am curious to hear the reasons for their naming, as there seem to be many discrepancies in there, mostly:

  • The use of both 'key' and 'name' for the same thing
  • The omitting of 'get' in Object.keys

In terms of a clean API, something along these lines would have seemed more consistent:

Object.getKeys Object.getOwnKeys

Actually, the implementation of these methods isn't corresponding much with method names.

Thus, "Object.keys" returns also only /own/ property names, but -- excluding those with [[Enumerable]] false.

And "Object.getOwnPropertyNames" does the same but including [[Enumerable]] = false.

Moreover, as I mentioned, "keys" name has nothing with current ECMAScript abstraction level. In contrast with other languages where there is separation of dot -- "." -- and bracket -- "[]" -- notations for property accessors, in ES there's no such discrimination. Therefore, here all of them are /properties/ and there is no devision on /keys/array indexes/properties/

So, Ruby, from which "Object.keys" was borrowed into Prototype.js library, in this case has exactly "keys" of a /hash/ -- and this name is acceptable. Because along with "keys" a hash also has "properties" and "methods". But not in ES, where there are only properties. "Object.keys" which contradicts to all other method names in ideology and stylistics (and has nothing with previous ES specs and implementations) in my opinion is error of the ES5 spec.

It is also relates to why term "hash" (often used to name ES objects), /regardless that on implementation level exactly this theoretical data structure can be used -- hash-table/ doesn't fit and is improper -- bit.ly/cA3bwY

So, ES has no "keys" concept.

As I am new to the community process of EcmaScript but strongly involved with the language for soon 10 years through projects like Scriptographer.org and Helma.org, and therefore concerned with the language's future, I am curious to find out more about these processes of the defining of the language's API and syntax.

Just two days ago the similar question has been raised, see: esdiscuss/2010-April/010908

Dmitry.

# Asen Bozhilov (15 years ago)

Jürg Lehni wrote:

I am aware that these function names are probably set in stone by now, but am curious to hear the reasons for their naming, as there seem to be many discrepancies in there, mostly:

  • The use of both 'key' and 'name' for the same thing
  • The omitting of 'get' in Object.keys

In terms of a clean API, something along these lines would have seemed more consistent:

Object.getKeys Object.getOwnKeys

Your suggestions are not quite clear, because Object.keys and Object.getOwnPropertyNames do different things. getOwnPropertyNames include properties which have [[Enumerable]] attribute equal to false. In other words include properties which are not enumerable. Object.keys include only enumerable properties, for which [[Enumerable]] is equal to true.

In nature of ES with method as Object.keys I expect property names, which are enumerable in whole prototype chain of passed object. With Object.keys I do not see any benefits. Again If there is:

for own(var i in obj) { }

Methods like those are not necessary. Or another approach is :

Object.prototype.forOwn = function(callback, thisValue) { /** * For next own property: * callback.call(thisValue, this[i], i, this); */ };

At the moment I need to get first array with properties names and second iterate over that array to do something with every property name. That is not improvements in the language. However regarding the names, you are correct they are not clear. For example:

Object.getOwnKeys -> Object.getOwnPropertyNames

Object.getOwnEnumKeys -> Object.keys

Is ES5 get idea for Object.keys by JS libraries, which use that method? For example Prototype.js?

# Jürg Lehni (15 years ago)

Thank you Dmitry and Asen for clarifying.

Of course you are both right, and I realised my proposal was wrong. But I do think Object.keys should have been named Objet.getOwnKeys or Objet.getKeys at least.

I am surprised to see a general lack of a clear convention regarding naming in the additions to the core API, especially given the history of Object.keys in one of the many JS libraries out there. It would not have been very hard for Prototype to do something along these lines in a new version instead:

Object.keys = Object.getOwnKeys || function(obj) { ... }

While these new additions seem really useful and were missing so far in the language specification, it seems they were generally defined in a quite negligent way.

Another example appears to be Object.defineProperty, where all the descriptor properties default to false, making the newly added property read-only, invisible, and protected against configuration, so pretty much the opposite of anything we were ever used to from adding properties to objects in EcmaScript so far.

While I agree that for such properties, enumerable should default to false, it seems it would have been better and made for more elegant code to let the others default to true, so they only would have to be explicitly set to false when needed. Or even better, they could have been defined as their opposites, so all values could default to false like in the current specification, e.g.: writable -> readOnly, configurable -> sealed

Object.defineProperty(name, { value: 10, readOnly: true, sealed: true });

And speaking of Object.defineProperty, is there anybody from Microsoft on this list who could explain how it was possible for them to only implement this feature for DOM nodes but not normal objects, although it is a Object generic, along with Object.getOwnPropertyDescriptor?

This really harms such language extensions, as they appear to exist, but do not function according to the specs, making ugly browser detection a necessity, and still removing the possibility to use getters / setters on the client side, with IE being the only major browser that continues to lack any of the two ways to define them (defineGetter being the other way).

Jürg

# Dmitry Soshnikov (15 years ago)

On Sun, Apr 18, 2010 at 7:15 PM, Asen Bozhilov <asen.bozhilov at gmail.com>wrote:

Jürg Lehni wrote:

I am aware that these function names are probably set in stone by now, but am curious to hear the reasons for their naming, as there seem to be many discrepancies in there, mostly:

  • The use of both 'key' and 'name' for the same thing
  • The omitting of 'get' in Object.keys

In terms of a clean API, something along these lines would have seemed more consistent:

Object.getKeys Object.getOwnKeys

<snip>

Object.getOwnKeys -> Object.getOwnPropertyNames Object.getOwnEnumKeys -> Object.keys

Is ES5 get idea for Object.keys by JS libraries, which use that method? For example Prototype.js?

Yes, and exactly from Prototype.js. And Prototype.js borrowed this method from Ruby, because first this library was developed as addition for Ruby on Rails framework. If you check out method names used in Prototype.js, you'll see that they are all borrowed from Ruby (those which are not borrowed from previously non-standardized JS extensions such as SM's forEach, map and other methods of arrays).

But Ruby also has interesting design and method names. And if ES could make some minor reservations (e.g. "some properties also can be named as keys" as it has "array-index" concept which still nevertheless a string property name), then other suggestions for method names can be made.

For example, more frequently user wants to get own property names, so there is no need to specify it explicitly. Then could be one method for that:

getPropertyNames()

and

getPropertyNames(true) will return also all inherited method names.

or more controllable:

getPropertyNames({ own: false, enumerable: [true, false] })

to get all -- own and inherited and regardless enumerable state.

Another variation:

getPropertyNames({ withInherited: true, enumerable: "both" })

but, maybe a bit ugly because of string "both" and too verbose.

The same can be for:

getValues(...)

If to specify "keys" concept then "getPropertyNames" can be replaced with "getKeys" or even "keys".

Because of object being the receiver can operate with delegated properties as its own, then /extended/ descriptor can have information (besides enumerable, configurable and so on) whether the property is /own/. Also "property" word in this method name can be omitted because descriptor relates only to properties.

var fooProperty = obj.getDescriptorOf("foo");

if (fooProperty.enumerable && !fooProperty.own) { // do something with real owner }

Although, can be getDescriptorForOwn("foo").

You can see some examples at gist.github.com/367080 (regardless my particular implementation for that; examples are at the bottom of the source); tested in Rhino 1.73.

But all this -- just a variation. Maybe in the future the committee will consider some of them.

Dmitry.