Prototypes as the new class declaration

Brendan Eich brendan at mozilla.com
Tue Jun 14 22:59:34 PDT 2011


On Jun 14, 2011, at 10:08 PM, Allen Wirfs-Brock wrote:

> The correspondence is even closer if we slightly extend the new operator.  Using current new operator semantics and my alternative way of defining SkinnedMeesh and then executing:
>   let aSM = new SkinnedMesh(aGeo, aMat);
> we would get a TypeError because SkinnedMesh does not have a [[Construct]] internal method.  However, it would be a small extension to the new operator for it to invoke its operand's constructor method if the operand is an object that is not a function (alternative, we could give every object created using an object literal a [[Construct]] internal method that invokes the constructor method, its really just an alternative way to specify the same thing.)

The extension to use .constructor seems better because less magic. Either way, there's an extension to runtime semantics that could make old code that fails (throws) today run tomorrow, but that is different from changing the meaning of non-failing code. Should be ok.

We should make a parallel change to instanceof, so (aSM instanceof SkinnedMesh) works.


> If we do all of this, we don't need a separate class declaration concept. We still have:
>    * a declarative way to abstract over a family of related objects -- an object literal
>    * a way to name these class-like abstractions -- a const or let binding
>    * a way to specify inheritance for the abstraction -- <|
>    * a way to specify how each instance of a class-like abstraction will differ -- the construct method defined in the object literal
>    * the ability to continue to use the new operator to create new instances of a named class-like abstraction -- extended new operator
>    * kept the basic JS focus on prototypal inheritance

I'm still ineffably sad about classes, but your proposal cures that melancholy. It's more JavaScript-y. I like it, so far.


> What we have dropped is a lot of complexity:
>    *  a new class declaration form
>    *  a emphasis on creating classes
>    *  class properties and their declarative forms.
>    *  parallel class-side inheritance hierarchy

Parallel class-side inheritance can be done, IINM:

const SkinnedMesh = THREE.Mesh <| {
  constructor: THREE.Mesh <| function(geometry, materials) {
    super.constructor(geometry, materials);
    ...
  },
  ...
};

This brings out a difference between your class-less proposal and classes, you've covered it but it may not pop out: you cannot call a class method cm via SkinnedMesh.cm()
. Instead you must call SkinnedMesh.constructor.cm() or equivalent.

Probably this is unfixable. The prototype object named here by SkinnedMesh is a singleton containing a single constructor function. Properties of the prototype show up, unless shadowed, in instances via delegation. Properties of the constructor, if inherited as I show above, come from the super-constructor. But there are no classes, so talking about class methods (never mind the "static" misnomer) does not make sense.

Constructor methods and other constructor properties can be created, but naming them requires that .constructor component.


>    *  issues concerning class-side private state
> 
> However, something we abandon is the constructor function/prototype abstraction model that the ES built-ins use and that is implicit in the current new operator definition and the association of a prototype property with each function.  This is a change, but perhaps one for the better.

This is where we may lose people. We're no longer sugaring the prototypal pattern as people know it.

/be
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110614/33082136/attachment.html>


More information about the es-discuss mailing list