An experiment using an object literal based class definition pattern

Axel Rauschmayer axel at rauschma.de
Thu Aug 4 20:39:10 PDT 2011


> From: Allen Wirfs-Brock <allen at wirfs-brock.com>
> Subject: An experiment using an object literal based class definition pattern
> Date: August 4, 2011 22:57:48 GMT+02:00
> To: es-discuss <es-discuss at mozilla.org>

> However, as current specified the [[Prototype]] of bar.prototype will be Object.prototype.  In other words,  bar inherits from foo but bar.prototype doesn't inherit from foo.prototype.  That seems unlikely to be the desired behavior in most situations.  We can fix that by specifying that if the RHS of <| is a function expression and the LHS is an object with a "prototype" property then the object that is the value of the "prototype" property of the new function object inherits from LSH.prototype rather than Object.prototype.

That is really cool, because it’ll give you inheritance for class methods and for instance methods (with the two being separate).

> Another idea was an alternative way to express the "extend" operator for literal property definitions.  Doug Crockford suggested the following syntax:
> 
>     obj.{
>        prop:1,
>        prop:2
>        }

It looks nice, but the operator should also work for a RHS that is not an object literal.

> This takes the properties defined in the object literal and adds then to obj (or replaces like named already existing properties).  An exception is thrown if they can't all be added.  Essentially .{ } is a postfix operator that extends an object with additional properties.
> 
> Using these two new ideas and other active object literal enhancement proposals it is pretty easy to compose a class-like declaration.  For example the SkinnedMesh from the http://wiki.ecmascript.org/doku.php?id=harmony:classes proposal can be code as:
> 
>   const SkinnedMesh = THREE.Matrix4.Mesh <| function(geometry,materials){
>     super.construtor(geometry,materials);
>     this.{
>       identity.Matrix: new THREE.Matrix4(),
>       bones: [],
>       boneMatrices: []
>     };
>   }.prototype.{
>     update(camera) {
>       ...
>       super(update);
>     }
>   }.constructor.{
>     default(){
>       return new this(THREE.defaultGeometry,THREE.defaultMaterials);
>     }
>   };



How about rewriting this as follows?

>   const SkinnedMesh = THREE.Matrix4.Mesh <| function(geometry,materials){
>     super.construtor(geometry,materials);
>     this.{
>       identity.Matrix: new THREE.Matrix4(),
>       bones: [],
>       boneMatrices: []
>     };
>   }.{
>     default(){
>       return new this(THREE.defaultGeometry,THREE.defaultMaterials);
>     }
>   }.prototype.{
>     update(camera) {
>       ...
>       super(update);
>     }

>   }; // possibly: }.constructor;


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. 

Another possibility: allow "extend" for properties in object literals (kind of a recursive overriding).

>   const SkinnedMesh = THREE.Matrix4.Mesh <| function(geometry,materials){
>     super.construtor(geometry,materials);
>     this.{
>       identity.Matrix: new THREE.Matrix4(),
>       bones: [],
>       boneMatrices: []
>     };
>   }.{
>     default(){
>       return new this(THREE.defaultGeometry,THREE.defaultMaterials);
>     },
>     prototype.{
>       update(camera) {
>         ...
>         super(update);
>       }
>     }

>   };


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
>         update(camera) {
>             ...
>             super(update);
>         }
>     }
> };

-- 
Dr. Axel Rauschmayer

axel at rauschma.de
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110805/be9397ef/attachment-0001.html>


More information about the es-discuss mailing list