(Weak){Set|Map} subclassing

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Dec 4 09:42:27 PST 2012

On Dec 4, 2012, at 7:21 AM, Erik Arvidsson wrote:

> Is there a missing step in that outlined algorithm? Where is [[Prototype]] set?
> So roughly speaking, Foo.[[Constructor]](...args) would be defined as:
> 1) Let creator be Foo.[[Get]](@@create)
> 2 ) Let newObj be creator.call(foo).  //Foo is passed as the this value to @@create
> 2.5) Call newObj.[[SetInheritance]](Foo.prototype)
> 3)  Let ctorResult be Foo.[[call]](newObj,args)
> 4)  If Type(ctorResult) is Object, return ctorResult
> 5) else return newObj

I do it in @@create:

> The definition of the Function.prototype.@@create would be loosely
> function() {
>     return Object.create(this.prototype);
> }

The this.prototype access gets the "prototype" property value from the leaf constructor ( in the example, Foo) and Object.create sets it upon creation.

I'm a bit reluctant to separate object allocation from initializing [[Prototype]] as I suspect that in many cases implementations will want to do these as an atomic step and separating them would be visible, via a Proxy.

On the other hand, requiring @@create to explicitly take care of setting [[Prototype]] maybe a bit of a foot gun.

Ideally, any @@create method that is just adding private state to an ordinary object should be coded as:

   //class methods of Foo
   [create] () {
      let newObj = super[create]();   //eventually calls Function.prototype.@@create.  We really need to allow super in obj lits to support this
      newObj[myPrivate] = undefined
      return newObj

If you forget to do the super[create] call you don't get [[Prototype]] initialized.  However, if you leave out that super call you will also not allocate any superclass provided per instance state.   So, it would be buggy anyway. 


More information about the es-discuss mailing list