An experiment using an object literal based class definition pattern

Axel Rauschmayer axel at rauschma.de
Fri Aug 5 04:34:30 PDT 2011


> But using . as the operator it would be ambiguous with normal property access.  A different and unique operator wouldn't have the problem but also wouldn't look so nice and the primary motivation for the operator is for use in expression such this post is about.  An alternative that could work would be to allow a parenthesized expression to follow the dot.

Agreed. I like the solution with parens. A method would be OK, too, I guess.

>> It seems more intuitive to me to add the constructor methods directly to the constructor, instead of returning to that function via prototype.constructor. The final ".constructor" is not as elegant as I would like, though. 
> 
> To me, the .prototype,{  and .constructor.{ feel very much like prototype: and class: compartment labels of the sort that was discussed a couple weeks ago.

Yes, I can see that. I really like the way it looks.

>> One more idea: If the constructor is becoming the class and has properties of its own, perhaps there is a way of writing a constructor function as an object literal, by giving an object literal a callable “body”.
>> 
>>> const SkinnedMesh = THREE.Matrix4.Mesh <| {
>>>     function(geometry,materials) {
>>>         super.constructor(geometry,materials);
>>>         this.{
>>>             identity.Matrix: new THREE.Matrix4(),
>>>             bones: [],
>>>             boneMatrices: []
>>>         };
>>>     }
>>>     default() {
>>>         return new this(THREE.defaultGeometry,THREE.defaultMaterials);
>>>     }
>>>     prototype: { // TODO: does not have the right prototype
> but you can explicitly set it using <|
>>>         update(camera) {
>>>             ...
>>>             super(update);
>>>         }
>>>     }
>>> };
> 

I thought about setting the prototype via <|, but didn’t like the redundancy.

> This is essentially what I showed in the second code snippet of my original post and is a technique that I used to create the non-constructable  base AbstractClass in my collections experiment.  It works ok for situations where you need to break the parallelism of the class/instance inheritance hierarchies which you tend to want to do at the root of a hierarchy.  However, for most situation, even when the class is abstract, I think it is best to follow the basic class pattern I provided.

Subjectively, I like to have an easily identifiable construct if concepts are reified in a language. Having things spread out like in your proposal (where the dependence on order also makes it feel brittle) seems less concise (even if it looks awfully nice). This line of arguing also makes me think that class literals might not be such a bad idea (easy tool support is another argument in their favor).

What I would propose is a new kind of object literal, because with constructors, the object nature of a function suddenly matters tremendously. Thus, you could flip things around as follows, if a function could be written like an object literal. That gives you a more compact single construct to represent a class.

== A function with extended properties ==

function(x, y) {
    ….
} . {
    prop1: value1,
    prop2: value2
}

== An object literal that is a function ==
{
    function(x, y) {
    }
    prop1: value1,
    prop2: value2
}


-- 
Dr. Axel Rauschmayer

axel at rauschma.de
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com





More information about the es-discuss mailing list