Prototypes as the new class declaration

Brendan Eich brendan at
Sat Jun 18 11:13:44 PDT 2011

On Jun 18, 2011, at 8:53 AM, Axel Rauschmayer wrote:

>>> Where would the prototype of the new instance come from? Would SkinnedMesh.constructor.prototype point to SkinnedMesh?
>> Of course -- Allen's proposal just "rotates" the (constructor, prototype) pair so the named or "outer" object is the prototype.
>> This matches the syntax. It's a bit odd that class syntax has a body that contains constructor, yet the class name binds to that inner constructor function. It works, or we can make it work -- it just seems unusual given the otherwise-pellucid rules for naming objects expressed by braced bodies (initialisers, functions).
> Right, I agree that the appeal of binding the prototype to the class name (instead of the constructor) is that everything makes more sense, especially instanceof and subclassing.
> I still don’t understand the “rotates” part, though. The following looks to me like a normal object literal (with the prototype set via the prototype operator). Nothing special about it.

I was responding to your question "Would SkinnedMesh.constructor.prototype point to SkinnedMesh?"

In the classes proposal, we have

[the binding environment] -- 'SkinnedMesh' -+
.                                           |
.                                           v
.                          [The class object, i.e., the constructor]
.                                  |                      ^
.                                  |                      |
.                             'prototype'           'constructor'
.                                  |                      |
.                                  v                      |
.                           [The object defined by the class body]

By "rotate" I meant turn the 2-cycle at the bottom 180 degrees.

>> const SkinnedMesh = THREE.Mesh <| {
>> constructor(geometry, materials) {
>>   super.constructor(geometry, materials);
>>   this.identityMatrix = new THREE.Matrix4();
>>   this.bones = [];
>>   this.boneMatrices = [];
>>   ...
>> }, 
>> update(camera) {
>>   ...
>>   super.update();
>> }
>> }
> Then I would have to make the following assignment:
>> SkinnedMesh.constructor.prototype = SkinnedMesh;

You don't need to, in Allen's proposal. But perhaps it was unclear, or even unstated.

> Now the following works (without a separate protocol):
>> var sm = new SkinnedMesh.constructor(...);

Allen's post discussed this.

> A next step would be the syntactic sugar suggested by Allen:
> new SkinnedMesh(...) => new SkinnedMesh.constructor(...)

Yes, and likewise for instanceof -- that all seems fine, although Irakli's gists can't work in JS today assuming such extensions, wherefore his 'new' protocol, which is clever.

> However: THREE.Mesh would have to refer to the prototype (similarly to how things are done above), for this to work.

Right. I thought we went over this already here :-).

The twist with Irakli's gist is that it adds a 'new' method that can work on old-style built-in and user-defined constructor functions, thanks to

But it is a new (no pun) protocol. It's not separate, though -- it works on old-style constructor functions. You can call for any instance x to get a new instance of the same class or built by the same constructor, provided is unshadowed.

(Irakli, you could pass along arbitrary arguments from to new this.constructor, in using rest and spread, and even in ES5 using the bind trick [].)

So Irakli's work suggests we don't need to extend new and instanceof if we're willing to switch to the new '.new()' protocol.

But that is a big switch.

Extending new and instanceof to probe for .constructor is plausible too, and it avoids breaking the use of these operators on prototype-first "new-style" abstractions.


More information about the es-discuss mailing list