Approach of new Object methods in ES5

Dmitry A. Soshnikov dmitry.soshnikov at gmail.com
Fri Apr 16 05:13:01 PDT 2010


Hello,

I'd like to clarify the question about approach used in ECMA-262-5 
regarding the code design for new methods of Object constructor.

I've read the section "Attribute Control API Design and Rationale" of 
"Proposed ECMAScript 3.1 Static Object Functions: Use Cases and 
Rationale" document: 
http://wiki.ecmascript.org/lib/exe/fetch.php?id=es3.1%3Aes3.1&cache=cache&media=proposals:proposal_to_refocus_tc39-tg1.pdf

I of course understand that now it is already too late to speak about 
it, because specification is already published. But nevertheless, maybe 
there is some hope to change something in new versions.

I think that approach used in ECMA-262-5 for new object methods 
contradicts ES nature. Of course, cases mentioned in that section of the 
document are correct and variations with "propertyIsDeletable", 
"propertyMakeEnumerable" as well as using a bit vector for handling 
property attributes (the descriptor) looks long and worse. So with these 
points everything's OK, they go without saying and can be omitted.

The point from that list with separation of Meta and App levels is 
interesting. But from this viewpoint all other methods of objects can be 
treated as meta-methods (such as "hasOwnProperty", "getPrototypeOf" and 
even "toString"). As well as e.g. bracket notation for property 
accessors which allows to access dynamic property names -- which is also 
kind of meta programming.

Accepted rules for new object methods -- that they should be directly in 
"Object" constructor instead of "Object.prototype" led to that now we 
have three (!) syntactically different approaches for the *same* 
semantically entity -- using methods of objects. These are:

- Object.keys();
- Object.get<SomeThing>();
- and the "old" approach such as foo.isPrototypeOf(bar);

I understand that "Object.keys()" is a kind of backward compatibility. 
But with what? With some js-libraty (in particular case I guess with 
"Prototype.js")?

First, the design of this method contradicts approved approach with 
"get" prefix (the second bullet), such as e.g. "getOwnPropertyNames".

Secondly, that is more essential, as ECMAScript uses the same semantics 
for the dot and bracket notations of property accessors, "keys" name can 
be improper. Because ES doesn't separate "keys/array 
indexes/properties", here all of them are "properties".

Thirdly, if to leave this "keys" and other similar "getters", maybe 
there was a sense to make them as real getters then? For example, 
o.keys, just like a.length (where "o" and "a" -- Object and Array 
instances accordingly). For what that useless call expression in this 
non-ideological "Object.keys()" method? And it still seems strange that 
it is just a "backward compatibility" with some library but not with 
previous version of language. In Ruby from which this "keys" methods was 
borrowed to "Prototype.js" there is separation in semantics of bracket 
and dot notations -- so there are "keys" in this case, but not 
"properties". In ES, I repeat, there is no such discrimination, so this 
"Object.keys()" looks odd for ES in contrast with all other new methods 
with "get" prefix.

Regarding the second bullet, all that "getters" (which are functions) 
also could be made as real getters:

o.ownProperties; // instead of Object.getOwnPropertyNames(o)

or "o.ownPropertyNames" if confusing that "property" isn't just a name, 
but property object with its descriptor. But this case isn't so 
essential, as is following.

Look at this (trivial, non-real, abstract) example:

var o = Object.freeze(
   Object.seel(
     Object.defineProperties(
       Object.create(proto),
       properties
     )
   )
);

And compare it with the following one:

var o = Object.create(proto)
   .defineProperties(properties)
   .seel()
   .freeze();

I know that we can define properties together with "Object.create", 
repeat -- this example is abstract. But it is obvious that the first 
example is harder to read and this repetition of "Object. - Object. - 
Object." with forced indention looks (in my opinion) worse.

Of course, we can provide own aliases for all that new methods and place 
them in "Object.prototype", like e.g. this one: 
http://gist.github.com/367080/ But this is just a compromise. Although, 
I prefer to use it in own projects improving the code reuse and avoiding 
this long repetitions of "Object. Object. Object." and similar. You 
talked about "long lines" in code when thinking about 
"propertyMakeEnumerable", but using this approach you provide also that 
long lines forcing to use this useless repetition of "Object." every 
time. Yeah, "propertyIsEnumerable" can be of course removed in some 
future (more radical) version, which will leave all old approaches (as 
Python did for 3.* version where some features are completely 
incomparable with 2.* versions -- and this is a good step for progress 
and do not carry all the time this old stuff).

Separating of "meta" and "app" of course is a good thing. But it is 
debatable what can be treated as "meta" level in this case. This cite 
from the mentioned above document looks really strange:

"/Object.prototype the methods would be part of the public interface of 
every application object in a program. As such, they need to be 
understood by every developer, not just library designers./"

Very strange cite. So, if I (and all) understand it correctly, all these 
new "meta" methods are just for library designers and should be (if 
possible) abstracted from "casual developer"? But of course it is not 
so, and all these methods will be used in every future code. Did you 
mean that user-defined object should contain only user-defined 
properties (with own invariants to be separated from other objects) and 
be like a simple hashtables without prototypes?

If any object can provide its string representation (using delegated 
"toString" from the prototype), why cannot it then get its "keys" using 
the same delegated approach? Why this action should be done by some 
"meta" (?) function? I think that "Object.prototype" /taking into 
account that in current API we can control [[Enumerable]] property/ is a 
good place for all base methods/properties of any object.

By the way, it is also petty that there's no ability to change prototype 
and there is only "get" function for that; __proto__ extension in this 
case was better.

Of course I do not blame ES5 or something. And this letter isn't an 
appeal all to change everything, of course not. But I just want to know 
what other members think about that new /design/. Maybe I do not see 
some very useful consequence of this new approach? I think it is as 
important as technical parts. Will you continue to develop the language 
in this stylistics? If so, we should change our approaches and ideology 
of ES-programming too.

Dmitry.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20100416/892ce9bb/attachment.html>


More information about the es-discuss mailing list