I want to give a +1 to Allen. The syntax really is 
what-you-see-is-what-you-get, which is a great virtue. The C++-derived 
initializer is cute and tempting, but not nearly as powerful or easy to grok.

That said, I feel weakly that requiring the correct `this = new 
super(...)`and/or `this = Object.create(new^.prototype)` invocation is a high 
price to pay for every derived class ever. In particular, "basic constructor 
functions" (ES5 "classes") that don't wish to use the superclass constructor 
don't need `this = Object.create(new^.prototype)`, so making ES6 classes 
require that is strange. It feels like protypal inheritance has "broken" once 
you start using ES6 classes, and it requires you to fix it by manually doing 
something that was previously implicit.

I think I'd most be in favor of a third option that implicitly adds `this = 
Object.create(new^.prototype)` if no `this`-assignment is present. That way, 
the superclass constructor is never implicitly called, which is kind of what 
you would expect. But if you do no `this =` assignment, things don't totally 
break: you still get your prototype and a valid `this`, but you don't inherit 
the allocation or initialization logic from the superclass. 


From: es-discuss [mailto:[email protected]] On Behalf Of Allen 
Wirfs-Brock
Sent: Monday, September 15, 2014 03:54
To: [email protected]
Cc: Jeff Morrison; Mark S. Miller; es-discuss
Subject: Re: new instantiation design alternatives


On Sep 14, 2014, at 4:23 PM, Brendan Eich wrote:


Kevin Smith wrote:

If we want to merge allocation with initialization, then I'm going to want to 
invoke C# (yet again):

   class ColoredPoint extends Point {
       constructor(x, y, color) : super(x, y) {
          this.color = color;
       }
   }

Gotta credt C#'s parents, C++, which would require Point not super.

I think you are really onto something here. We do not want anything looking 
like an expression-statement in the constructor body, which besides being 
verbose has unwanted degrees of freedom (requiring TDZ for `this`, running into 
the dead code problem Jeff cited, etc.).

the dead code problem (and we can debate whether it is actually a significant 
problem) goes away with alternative 2 (no automatic mew super in derived class 
constructors. 

The TDZ constrained `this` is an elegant solution which we had a good consensus 
on at the last TC39 meeting. Since then we have developed has it further 
unifies various allocation patterns that come up in JS object constructions.  
Everybody really need to really work through all the use cases given in the 
Gists and similarly work through them all with what every other alternatives 
they may think would be better. 


It sure seems to me that we rather want a special form in the constructor head. 
This came up in ES4.

the C/C# constructor header approach butts heads with other ES features and 
isn't expressive for the sort of dynamic classes that ES allows.

In terms of headbutting, consider

`constructor({a: x, b: y), [a1,a2,a3,...arest], c ) : super(??, ??) {}//  what 
do I put here to super call the constructor with only the first two arguments)`

perhaps:

`constructor{a: x, b: y), [a1,a2,a3,...arest], c ) : super(arguments[0], 
arguments[1]) {}`

but that means that the special header form must allow arbitrary expressions.  
Are those expression in the parameter scope of the body scope.

Most importantly, a single constrained expression isn't expressive enough.  The 
problem, is that a subclass constructor may need to perform arbitrary compelx 
computations before super newing the its base constructor.  For example, 
consider a TypeArray subclass constructor that filters various collections 
passed to to the derived  constructor to produce a simple list iterator that it 
passed to the  base constructor.

The constrained super expression is a slippery slope that leads you to a cliff. 
Better to go with the full generality and expressiveness of the function body.


Separately I agree `this = new super(x, y);` is just crazy long and very likely 
to be left out in whole or in part (the `new`).

If left-out, programs will fail quickly and noisily (reference errors) 
especially with the no auto super design alternative.

And this hardly seems like a significant length issue as we are talking about 
something that at typically occurs only once per subclass with an extends 
clause. And not even for all subclasses.

and ignoring white space we are taking about either +5 characters ("this=") or 
8 characters ("this=new") if you think the alternative is is just "super" 
without a "new".  But in https://gist.github.com/allenwb/291035fbf910eab8e9a6 
we addressed why it is really a bad idea to make "super(a,b)"  be a 
[[Construct]] operation rather than a [[Call]] operation. Basically, JS is 
currently very consistent in that `new foo()` and `foo()` do not have the same 
language level meanings.  It would be a big WTFJS if we changed things such 
that  sometimes the syntax for a [[Call]] really means a [[Construct]].  
Especially, if that meaning is dependent upon how the enclosing function was 
invoked rather than being statically determined.  Example, in the rationale 
document.

As I mentioned a couple of times in conversations, those of use who worked on 
developing this design found that the syntax really grows upon you.  It's big 
advantage is that is is unambiguously explicit.  If you want to invoke a 
constructor "as a constructor" you always say `new`. `new foo()` or new 
super(), it doesn't make a difference, `new` always means [[Constructor]]. If 
you want to invoke a constructor "as a function" you do a normal function 
invocation.  Again, either `foo()` or `super()`.  It's the same.  The [[Call]] 
syntax is never repurpose to mean [[Construct]] so there are no special cases 
to explain or remember.  Also, if you want to designate the `this` value used 
within a constructor you always explicit say `this=`, whether it is `this = 
super()' or `this=mayFactoy()` or `this = new Proxy(new super(), {...});`. 
Again, it is always explicit, no magic `super` calls that magically sets `this` 
as a side-effect.

It's this explicitness that grows on you.  The code actually says what it means.

Allen

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to