Object.keys(): Why no inherited properties?

# Felipe Gasper (14 years ago)

Why does Object.keys() not allow, as an option, iterating through inherited properties?

# David Bruant (14 years ago)

Le 07/09/2011 17:33, Felipe Gasper a écrit :

Why does Object.keys() not allow, as an option, iterating through inherited properties?

I do not have the answer to this very question. However, if you want to iterate through all (own and inherited) enumerable properties, you can use a for-in loop.

# Dmitry Soshnikov (14 years ago)

On 07.09.2011 19:33, Felipe Gasper wrote:

Why does Object.keys() not allow, as an option, iterating through inherited properties?

Because it's the same version that is from Prototype.js. I guess it was ported "as is" for compatibility with the library. But IMO, yes, native implementation could provide at least an option for this case (if needed). Though, that's said, you may implement in your way using for-in or getOwnPropertyNames + getPrototypeOf.

Dmitry.

# Brendan Eich (14 years ago)

On Sep 7, 2011, at 9:29 AM, Dmitry Soshnikov wrote:

On 07.09.2011 19:33, Felipe Gasper wrote:

Why does Object.keys() not allow, as an option, iterating through inherited properties?

Because it's the same version that is from Prototype.js. I guess it was ported "as is" for compatibility with the library. But IMO, yes, native implementation could provide at least an option for this case (if needed).

If you mean that an ES5-conforming implementation could add an optional boolean parameter to Object.keys, to get inherited enumerable properties too, then please, no: that is against the NOTE in Clause 15 (quoting from ES5.1):

NOTE Implementations that add additional capabilities to the set of built-in functions are encouraged to do so by adding new functions rather than adding new parameters to existing functions.

I think we should make this a normative restriction in ES6.

# Mark S. Miller (14 years ago)

On Wed, Sep 7, 2011 at 9:53 AM, Brendan Eich <brendan at mozilla.com> wrote: [...]

NOTE Implementations that add additional capabilities to the set of built-in functions are encouraged to do so by adding new functions rather than adding new parameters to existing functions.

I think we should make this a normative restriction in ES6.

+100.

The SES whitelisting mechanism, where we remove all non-standard properties not on our whitelist < code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/whitelist.js>,

only protects under the assumption that this restriction is upheld. While we could instead whitelist by name+arity, it would be a too expensive. In addition to removing everything absent from our whitelist, we'd have to wrap everything present on our whitelist. And even that still wouldn't be sound if implementors might still enable new abilities by, e.g., type-based overloads.

We should also promote the recommendation at < conventions:make_non-standard_properties_configurable>

to normative status, so that such whitelisting mechanisms are possible.

I believe these two constraints together are equivalent to the constraints enumerated at code.google.com/p/es-lab/wiki/SecureableES5. While

I'm sure this list is incomplete, and the Ch16 exemptions need to be further restricted somehow, these two are still a great start.

Btw, to avoid terminology confusion, I use "abilities" in sentences like yours when it works. In this case, it is precisely the mapping of such abilities onto capabilities that is at stake ;).

# Dmitry Soshnikov (14 years ago)

On 07.09.2011 20:53, Brendan Eich wrote:

On Sep 7, 2011, at 9:29 AM, Dmitry Soshnikov wrote:

On 07.09.2011 19:33, Felipe Gasper wrote:

Why does Object.keys() not allow, as an option, iterating through inherited properties?

Because it's the same version that is from Prototype.js. I guess it was ported "as is" for compatibility with the library. But IMO, yes, native implementation could provide at least an option for this case (if needed). If you mean that an ES5-conforming implementation could add an optional boolean parameter to Object.keys, to get inherited enumerable properties too, then please, no: that is against the NOTE in Clause 15 (quoting from ES5.1):

No, I just explained from where the roots of Object.keys() -- from Prototype.js. It was just ported "as is", though, IMO, when it was porting, it with the same success could accept this additional parameter. And I assumed that it was ported as is only because to support compatibility with the Prototype.js.

NOTE Implementations that add additional capabilities to the set of built-in functions are encouraged to do so by adding new functions rather than adding new parameters to existing functions.

I think we should make this a normative restriction in ES6.

Yes, of course, I think it's way it should be.

Dmitry.

# Allen Wirfs-Brock (14 years ago)

On Sep 7, 2011, at 11:27 AM, Dmitry Soshnikov wrote:

On 07.09.2011 20:53, Brendan Eich wrote:

On Sep 7, 2011, at 9:29 AM, Dmitry Soshnikov wrote:

On 07.09.2011 19:33, Felipe Gasper wrote:

Why does Object.keys() not allow, as an option, iterating through inherited properties?

Because it's the same version that is from Prototype.js. I guess it was ported "as is" for compatibility with the library. But IMO, yes, native implementation could provide at least an option for this case (if needed). If you mean that an ES5-conforming implementation could add an optional boolean parameter to Object.keys, to get inherited enumerable properties too, then please, no: that is against the NOTE in Clause 15 (quoting from ES5.1):

No, I just explained from where the roots of Object.keys() -- from Prototype.js. It was just ported "as is", though, IMO, when it was porting, it with the same success could accept this additional parameter. And I assumed that it was ported as is only because to support compatibility with the Prototype.js.

Nice theory, but not the way it actually went down. We wanted to provide a function for use in application code that was guaranteed to order the own property names of an object in the same implementation specific order used by for-in. Use in conjunction with the "Array extras" was contemplated. For simple "flat" collections of properties we want to enabling enumerating over them using the array functions instead of for-in but also to ensure that the processing order would be the same regardless of which technique was used.

It was thought of as a application layer function rather than as a reflection function. That was why it was given a simple, short name rather than being called something like getOwnEnumerablePropertyNames. I believe that Crockford suggested the name but it might have been someone else. "keys" was an obvious name choice as we were thinking about operating on objects that represented collections of key/value pairs.

I don't recall Prototype.js ever being mentioned in the discussions. I

# Mark S. Miller (14 years ago)

On Thu, Sep 8, 2011 at 9:16 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

On Sep 7, 2011, at 11:27 AM, Dmitry Soshnikov wrote:

No, I just explained from where the roots of Object.keys() -- from Prototype.js. It was just ported "as is", though, IMO, when it was porting, it with the same success could accept this additional parameter. And I assumed that it was ported as is only because to support compatibility with the Prototype.js.

Nice theory, but not the way it actually went down. We wanted to provide a function for use in application code that was guaranteed to order the own property names of an object in the same implementation specific order used by for-in. Use in conjunction with the "Array extras" was contemplated. For simple "flat" collections of properties we want to enabling enumerating over them using the array functions instead of for-in but also to ensure that the processing order would be the same regardless of which technique was used.

It was thought of as a application layer function rather than as a reflection function. That was why it was given a simple, short name rather than being called something like getOwnEnumerablePropertyNames. I believe that Crockford suggested the name but it might have been someone else. "keys" was an obvious name choice as we were thinking about operating on objects that represented collections of key/value pairs.

I don't recall Prototype.js ever being mentioned in the discussions. I

I do. We wanted something with this functionality for all the reasons you state. Since Prototype already had one, we just adopted it as is, as Dmitry surmised.

# Dmitry Soshnikov (14 years ago)

On 08.09.2011 20:16, Allen Wirfs-Brock wrote:

On Sep 7, 2011, at 11:27 AM, Dmitry Soshnikov wrote:

On 07.09.2011 20:53, Brendan Eich wrote:

On Sep 7, 2011, at 9:29 AM, Dmitry Soshnikov wrote:

On 07.09.2011 19:33, Felipe Gasper wrote:

Why does Object.keys() not allow, as an option, iterating through inherited properties?

Because it's the same version that is from Prototype.js. I guess it was ported "as is" for compatibility with the library. But IMO, yes, native implementation could provide at least an option for this case (if needed). If you mean that an ES5-conforming implementation could add an optional boolean parameter to Object.keys, to get inherited enumerable properties too, then please, no: that is against the NOTE in Clause 15 (quoting from ES5.1):

No, I just explained from where the roots of Object.keys() -- from Prototype.js. It was just ported "as is", though, IMO, when it was porting, it with the same success could accept this additional parameter. And I assumed that it was ported as is only because to support compatibility with the Prototype.js.

Nice theory, but not the way it actually went down. We wanted to provide a function for use in application code that was guaranteed to order the own property names of an object in the same implementation specific order used by for-in. Use in conjunction with the "Array extras" was contemplated. For simple "flat" collections of properties we want to enabling enumerating over them using the array functions instead of for-in but also to ensure that the processing order would be the same regardless of which technique was used.

Maybe it was also mentioned as a reason in that discussion. Though, I don't see a big practical usage of this (perhaps maybe except of only convenience in some functional programming cases; e.g. when you need to pass the property names aka "keys" to some function which will enumerate them). In real practical examples it's just inefficient to collent the properties first and the to go over them via forEach of arrays. Simple for-in is enough.

I would better implemented then Object.forEach or Object.forAll higher-order functions.

It was thought of as a application layer function rather than as a reflection function. That was why it was given a simple, short name rather than being called something like getOwnEnumerablePropertyNames.

Sure.

I believe that Crockford suggested the name

No, maybe Crockford just gave the publicity on meetings, but clearly the method was borrowed from Prototype.js.

What's the most funny in this story is that Prototype.js borrowed the method from Ruby (actually, Prototype.js initially was written only for Ruby on Rails framework). The whole library is inspired by the Ruby and the idea of monkey-patching -- this is why Prototype.js augments built-ins: Array.prototype, String.prototype, etc (Rails uses this technique heavily also).

Unfortunately, authors of Prototype.js couldn't augment Object.prototype because the library was developed in the times of ES3-only -- that is, they cannot control enumerable (DontEnum) attribute there. However, if the had such an ability it's clear 100% that the method keys would be an instance method, the same as it is in Ruby.

Ruby:

foo = {:x => 10, :y => 20}

print foo.keys # [:x, :y]

The other thing to note, that JS in contrast with Ruby doesn't have concept of a "key" (all of them are "properties"). In Ruby these two entities are separated: keys are accessed by the square bracket notation, and properties via dot-notation (the same separation by the way in Python).

So the thing is that the terminology, implementation, etc are borrowed from Ruby, but it doesn't correlates with JS terminology. OTOH, who cares about terminology much if the method is useful? That's why it's borrowed and standardized as it's standardized. Moreover, since we have a "virtual" concept of an "array index", then we have the same "virtual" concept of a "key" as "own enumerable property". So everythings fine here, and regarding initial letter "why not to have a flag to get inherited properties" -- it's also from Ruby and handled there in the same way -- for foo.methods method (own methods) and foo.instance_methods(true) -- including inherited.

but it might have been someone else.

Initially -- authors of Prototype.js, borrowing form Ruby. But I don't know -- maybe it was Crockford on the meetings as you mention. Anyway, it doesn't matter much.

"keys" was an obvious name choice as we were thinking about operating on objects that represented collections of key/value pairs.

Yes, this is true.

Dmitry.