admin管理员组

文章数量:1388835

Now that JavaScript has classes I'm wondering how it is possible to invoke a super constructor outside of a class constructor.

My unsuccessful naive attempt (results in a SyntaxError):

class A
{
    constructor() { this.a = 1; }
}

function initB()
{
    super(); // How to invoke new A() on this here?
    this.b = 2;
}

class B extends A
{
    constructor() { initB.call(this); }
}

I'm aware that in some other language like Java a super constructor can only be invoked inside the constructor of a derived class, but ES6 classes are syntactic sugar for prototype-based inheritance, so I'd be surprised if this were not feasible using built-in language features. I just can't seem to figure out the proper syntax.

The best I've e with so far feels terribly like cheating:

class A
{
    constructor() { this.a = 1; }
}

function initB()
{
    let newThis = new A();
    newThis.b = 2;
    return newThis;
}

class B extends A
{
    constructor() { return initB(); }
}

Now that JavaScript has classes I'm wondering how it is possible to invoke a super constructor outside of a class constructor.

My unsuccessful naive attempt (results in a SyntaxError):

class A
{
    constructor() { this.a = 1; }
}

function initB()
{
    super(); // How to invoke new A() on this here?
    this.b = 2;
}

class B extends A
{
    constructor() { initB.call(this); }
}

I'm aware that in some other language like Java a super constructor can only be invoked inside the constructor of a derived class, but ES6 classes are syntactic sugar for prototype-based inheritance, so I'd be surprised if this were not feasible using built-in language features. I just can't seem to figure out the proper syntax.

The best I've e with so far feels terribly like cheating:

class A
{
    constructor() { this.a = 1; }
}

function initB()
{
    let newThis = new A();
    newThis.b = 2;
    return newThis;
}

class B extends A
{
    constructor() { return initB(); }
}
Share Improve this question edited Mar 29, 2016 at 0:07 GOTO 0 asked Mar 28, 2016 at 23:51 GOTO 0GOTO 0 48.1k25 gold badges139 silver badges164 bronze badges 6
  • 1 What's preventing you from using the standard class B extends A { constructor() { super(); this.b = 2; }}, as it is supposed to be? – Bergi Commented Mar 28, 2016 at 23:56
  • Your "solution" is in fact a syntax error. – Bergi Commented Mar 29, 2016 at 0:04
  • @Bergi I know my first approach is a syntax error, that's why I'm asking. I clarified my question, thanks. – GOTO 0 Commented Mar 29, 2016 at 0:07
  • Actually I meant the second one. Yes, your first snippet is a syntax error as well. – Bergi Commented Mar 29, 2016 at 0:08
  • 1 The constructor doesn't contain a super() call. Babel gets this right, for example. – Bergi Commented Mar 29, 2016 at 0:15
 |  Show 1 more ment

1 Answer 1

Reset to default 6

Every constructor of a class that extends something must contain a direct super(…) call.
Direct super(…) calls can only be placed in constructors. There's really no way around this.

You really should not place the initialisation logic of a class anywhere else than in its constructor. The straightforward and proper solution is not to use initB at all:

class A {
    constructor() { this.a = 1; }
}

class B extends A {
    constructor() {
        super();
        this.b = 2;
    }
}

That said, there is a way to subvert the "super() call must be in the constructor" requirement. Putting it inside an arrow function counts as well! So you could do

class A {
    constructor() { this.a = 1; }
}

function initB(_super) {
    var b = _super();
    b.b = 2;
}
class B extends A {
    constructor() {
        initB(() => super());
    }
}

Promise me to not ever do that, please.

Another pattern is not to call super() at all, which works as long as you return an object from the constructor. With that, you can put the actual construction of the object anywhere else:

class A {
    constructor() { this.a = 1; }
}

function makeB() {
    var b = Reflect.construct(A, [], B); // call the A constructor with B for the prototype
    b.b = 2;
    return b;
}
class B extends A {
    constructor() {
        return makeB();
    }
}

Which really isn't much better.

本文标签: javascriptHow do I call a super constructor outside a constructorStack Overflow