super() call in methods

# Bergi (10 years ago)

I've just read the spec draft on the super keyword to answer a StackOverflow question.

From what I understood, it's currently not possible call a super method using only super(), contrary to common (my?) intution. A quick web search shows that other people think similar:

www.2ality.com/2011/11/super-references.html (with a 2013 update):

Super-references (including super-calls) are a feature of ECMAScript 6 which allows one to write describe() much more succinctly:

Employee.prototype.describe = function () {
    // super() is an abbreviation of super.describe()
    return super()+" ("+this.title+")";
};

Although they look similar, super and this are independent features. super means “I’m currently in a method – find the method that that method has overridden and apply it to the same instance that is presently active (i.e., this stays the same)”

javascriptplayground.com/blog/2014/07/introduction-to-es6-classes-tutorial/:

class LogView extends View {
  render() {
    var compiled = super();
    console.log(compiled);
  }
}

We first call super(). This calls the parent class' render() method, and returns the result. This means that the render method on the View class is first called, and the result is stored in the compiled variable.

esdiscuss.org/topic/base-value-of-super-reference-indicates-the-prototype-object-of-the-current-derived-class:

class Base {
  say() {
    console.log('base');
  }
};

class Derived extends Base {
  say() {
    console.log('derived');
    super();
  }
};

let instance = new Derived;
instance.say();

I've read esdiscuss.org/topic/referencing-super and it seems that needing to call super.describe()/super.render()/super.say() is intended behaviour. I'm fine with that, as explicit is better than implicit and "finding the method with the same name" (or something like that) is overly complicated and maybe even ambiguous.

However, it seems that we need to communicate better that super() calls only work in constructors, and other functions that inherit from functions (people.mozilla.org/~jorendorff/es6-draft.html#sec-getsuperconstructor).

That seems to be the reason why the method name GetSuperConstructor() was chosen in the spec. Yet, super() calls in plain methods would actually work! The method objects would inherit from Function.prototype, which is itself callable: a no-op function. This might lead to subtle bugs, where super() was intended to call the parent class's method, but does nothing - not even throwing an error!

Should an exception been thrown if the func returned by GetSuperConstructor() is %FunctionPrototype%?

PS: there's a typo in GetSuperConstructor: s/activeFuntion/activeFunction/

# Allen Wirfs-Brock (10 years ago)

On Dec 16, 2014, at 1:18 PM, Bergi wrote:

...

I've read esdiscuss.org/topic/referencing-super and it seems that needing to call super.describe()/super.render()/super.say() is intended behaviour. I'm fine with that, as explicit is better than implicit and "finding the method with the same name" (or something like that) is overly complicated and maybe even ambiguous.

Yes, this is a fairly recent change to the ES6 draft specification. People who write public commentary and tutorials about ES6 need to keep up with evolving spec. changes.

However, it seems that we need to communicate better that super() calls only work in constructors, and other functions that inherit from functions (people.mozilla.org/~jorendorff/es6-draft.html#sec-getsuperconstructor). That seems to be the reason why the method name GetSuperConstructor() was chosen in the spec.

Rev 29 made new super and new super ( ) early errors in non-constructor concise methods. It doesn't do the same thing for super( ) calls that appears to be an editorial mistake that I will correct in Rev 30.

Yet, super() calls in plain methods would actually work! The method objects would inherit from Function.prototype, which is itself callable: a no-op function. This might lead to subtle bugs, where super() was intended to call the parent class's method, but does nothing - not even throwing an error!

Should an exception been thrown if the func returned by GetSuperConstructor() is %FunctionPrototype%?

It it [[Prototype]] was set ot %FunctionPrototype% from a different realm?

I think the early error described above is a better solution as it address the syntactic context of the usage rather than actual runtime value.

# Bergi (10 years ago)

Allen Wirfs-Brock schrieb:

Yes, this is a fairly recent change to the ES6 draft specification. People who write public commentary and tutorials about ES6 need to keep up with evolving spec changes.

Sure they do, but I didn't even know that there was an earlier revision where this had once worked. Thanks for the clarification!

Rev 29 made new super and new super ( ) early errors in non-constructor concise methods.

Ah, people.mozilla.org/~jorendorff/es6-draft.html#sec-object-initializer-static-semantics-early-errors and people.mozilla.org/~jorendorff/es6-draft.html#sec-class-definitions-static-semantics-early-errors.

I had not seen that.

It might be nice if there was a note about these in the Static Semantics for the super keyword productions (people.mozilla.org/~jorendorff/es6-draft.html#sec-super-keyword-static-semantics-early-errors)

It doesn't do the same thing for super( ) calls that appears to be an editorial mistake that I will correct in Rev 30.

Thanks!

I think the early error described above is a better solution as it address the syntactic context of the usage rather than actual runtime value.

Yes indeed. This will fit the needs of the majority who declare their methods in object literals or classes much better than a runtime exception (which was just the first idea that had come to my mind). And we probably don't need to care about those who manually assign functions and call .toMethod() etc.

However, I wonder whether the same thing should be done in non-concise method assignments, i.e. PropertyDefinition : PropertyName : AssignmentExpression. As the PropertyDefinitionEvaluation handles the "IsFunctionDefinition of AssignmentExpression" case specially, I think the static semantics for it should do so as well (and forbid super calls in them).

# Allen Wirfs-Brock (10 years ago)

On Dec 16, 2014, at 4:18 PM, Bergi wrote:

However, I wonder whether the same thing should be done in non-concise method assignments, i.e. PropertyDefinition : PropertyName : AssignmentExpression. As the PropertyDefinitionEvaluation handles the "IsFunctionDefinition of AssignmentExpression" case specially, I think the static semantics for it should do so as well (and forbid super calls in them).

But there is a difference here. Functions defined in this manner are constructors (the support [[Construct]] while concise methods are not.