Prototypes as the new class declaration

Allen Wirfs-Brock allen at
Tue Jun 14 22:08:19 PDT 2011

In I described how self uses an explicit copy method on prototypes to construct instance objects and summarized the difference between self and JavaScript in this regard as:

> So, there is pretty much a directly correspondence between a self copy method and a JavaScript constructor function.  However, there is definitely a difference of emphasis seen here.  In self, it is the prototype object that is the focus of attention.  In traditional JavaScript it is the constructor object.
(emphasis added)

 In response to a reply from Axel I further said:

> A prototype P, as used in self, does seem to frequently subsume the role of a class.  A constructor  generally corresponds to the copy method of such a prototype.

Having thought about this a bit more, I'm beginning to think that perhaps we could get by without the proposed class declarations.  Consider the basic example from the classes proposal:

class SkinnedMesh extends THREE.Mesh {
  constructor(geometry, materials) {
    super(geometry, materials);
    public identityMatrix = new THREE.Matrix4();
    public bones = [];
    public boneMatrices = [];
  update(camera) {
You instantiate an instance of this class by saying:
  let aSM = new SkinnedMesh(aGeo, aMat);
Now consider rewriting using proposed object literal extensions as:

const SkinnedMesh = THREE.Mesh <| {
  constructor(geometry, materials) {
    super.constructor(geometry, materials);
    this.identityMatrix = new THREE.Matrix4();
    this.bones = [];
    this.boneMatrices = [];
  update(camera) {
Given this declaration, you could  create a new instance by:
  let aSM = new SkinnedMesh.constructor(aGeo, aMat);
The object literal  form is very similar to the class declaration form except that the entity that we named and which serves as the conceptual focus of abstraction is the prototype object rather than the constructor object.

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.)  BTW, I believe that somebody else recently on one of these threads also suggested allowing the new operator to be applied to any object so feel free to take credit.

If we extend new in this manner we are now able to name and use prototype objects defined using object literals as if they were class abstractions.  The only thing we are missing at this point is various extensions such as private state and declarative definition of instance properties in constructors that we have in the class declaration proposals.  However, those same extensions can be incorporated into object literals in same manner to how they are defined for class declarations.  In particular we would allow public and private property declarations in the constructor body, just like in the class proposal.

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

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
   *  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.

When Brendan originally created JavaScript he was operating under directions to make it as Java-like possible.  The use of constructor functions in association with the new operator were part of that Java-like facade. But this was arguably a left turn away from the prototypal inheritance that is at the core of the language.  Maybe instead of going further down that side street we can just get back on track by changing how we think about object construction and abstraction.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list