new instantiation design alternatives

Allen Wirfs-Brock allen at wirfs-brock.com
Wed Sep 17 10:29:58 PDT 2014


On Sep 16, 2014, at 4:55 PM, Brendan Eich wrote:

> ...
> It would help, I think, if you replied to Kevin's mail dated 12:05pm yesterday, which ended:
> 
> """
> Well, what I'm trying to point out is that it's always an error to set "this" if "new^" is undefined.  So it's kind of strange to force the user to explicitly write that conditional:
> 
>    constructor(x, y) {
>        if (new^)
>            this = new super(x);
>        this.y = y;
>    }
> 
> With the header approach, it's taken care of:
> 
>    constructor(x, y) : super(x) {
>        this.y = y;
>    }
> 
> (using colon just to avoid bikeshedding)
> """


actually I did respond:

On Sep 15, 2014, at 11:24 AM, Allen Wirfs-Brock wrote:

> 
> On Sep 14, 2014, at 8:48 PM, Kevin Smith wrote:
> 
>> 
>> 
>> It seems to me that with the proposed design we're going to have to branch on "new^" continually:  if we don't, then the function will always fail if [Call]'ed and it contains a this-setter.
>> 
>> With the class create expression approach, that branch is taken care of automatically.
> 
> If you want a [[Call]] to the constructor to do an implicit `new`, then you need to branch on `new^`:
> 
> 
>    constructor (a,b,c) {
>       if (!new^) return new C(a,b,c);
>       // continue with instance initialization code
>    }
> }
> 
> But [[Call]] same as [[Construct]] is not normal default JS behavior, so it shouldn't be unexpected that you need to explicitly say something if that is what you want.  The whole point of new^ is that a constructor function that wants differing call vs construct behavior needs to explicitly implement the alternatives. Just like today, if you only want your constructors to support one or the other of [[Call]]/[[Construct]] you code for what you care about and errors will occurs if it is invoke the other way. 
> 
> Allen
> 

or using your above example.

Most people today don't explicitly deal with constructors called as functions. If you con't care you probably just write 

constructor(x, y) {
       this = new super(x);
       this.y = y;
   }

and a runtime error will occur if it is called "as a function".

If you want  to also support "called as a function", say to do a `new` like above you would probably code:

class C extends B {
  constructor(x, y) {
      if (!new^) return new C(x,y);
      this = new super(x);
      this.y = y;
   }
}

So you only need to branch on `new^` if you want to explicitly support both constructor and function behavior.  

Allen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140917/c01c2979/attachment.html>


More information about the es-discuss mailing list