Allen Wirfs-Brock wrote:
super(...) is just shorthand for super.constructor(...) (when it
occurs in a constructor) so it is just a use of [[Call]]. No magic.

[[Call]]/[[Init]] aside.

After reading the spec, it is really so that super(...) in constructor is in fact super.constructor(...), because
 - constructor has MethodName "constructor"
 - super(...) has generic super[MethodName](...) semantics.
IOW, constructor is compiled as any other method with respect to semantics of its code (it gains its [[Construct]] and .prototype magic later, but these are external and do not touch the code).

It is bad for two reasons:

1. It will fail. There is lot of examples of code like:

  function Foo() { ... }
  Foo.prototype = Object.create(Bar.prototype);
  // or even (!!!) Foo.prototype = new Bar();
  Foo.prototype.baz = function () {...};
  ...

all over the web, in libraries etc.
Some people add "Foo.prototype.constructor = Foo;" there, but some don't. Now you see what happens if I try to use the new class:

  class Quux extends Foo {
    constructor() { ....; super(...); ... }
  }

super(...) call fails, because there is no Foo.prototype.constructor.

What's additional risk, the .constructor can be writable/configurable, so something may be injected / it may be deleted. It is not what developers assume. This relates to the:

2. It is not right (imho). Constructors are not methods (is there a movement of making them into ones? I doubt, constructor methods are too in-grained in the ECMAScript structure).

Constructors are not methods, they are much more external to the class. They _are_ the class, so what nearly every developer assumes when calling super(...) in the constructor with extends Foo to call Foo. Not Foo.prototype.constructor, which is way too brittle.

It is the common practice now, Foo.apply(this, arguments) or Foo.call(this, ...). The ES6 super(...) does something else.


Therefore, I propose super(...) has different semantics for constructor methods*. It should do roughly (ctr being the constructor function):

1. Get [[Prototype]] of ctr into proto, fail if problem.
2. If proto is constructor function,
2.1. [[Call]]** proto with thisArg of this, and argument list equal to super(...) argument list
  2.2. return the completion of 2.1.
3. Otherwise, throw.***

Allen

Herby

* That is, I'd like to see it in freeform constructor methods as well. Only with super(...) shortened form. It's semantics is straightforward and prompts replacing Bar.call(this, ...) with saner super(...); of course, one must rewire Foo.__proto__ = Bar; to get this. May help the transition and understanding that class has constructor inheritance as well, not only prototype inheritance.
** Or [[Init]] if adopted.
*** Alternatively, revert to super.constructor(...). I don't like it, though.
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to