如何在构造函数外调用超级构造函数? [英] How do I call a super constructor outside a constructor?

查看:144
本文介绍了如何在构造函数外调用超级构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

既然JavaScript有类,我想知道如何在类构造函数之外调用超级构造函数。

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

我不成功的天真尝试(导致一个SyntaxError):

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); }
}

我知道在Java之类的其他语言中,超级构造函数可以只能在派生类的构造函数中调用,但ES6类是基于原型的继承的语法糖,所以如果使用内置语言功能不可行,我会感到惊讶。我似乎无法弄清楚正确的语法。

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 come 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(); }
}


推荐答案

扩展类的每个构造函数必须包含直接 super(...) call。

直接 super(...)调用只能放在构造函数中。实际上没有办法解决这个问题。

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.

你真的不应该把类的初始化逻辑放在除了构造函数之外的任何地方。直截了当的解决方案是不要使用 initB

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;
    }
}

这就是说,有办法颠覆 super()调用必须在构造函数要求中。把它放在箭头里面也很重要!所以你可以做到

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.

另一种模式根本不是调用 super(),只要你从中返回一个对象就可以了。构造函数。有了这个,你可以把对象的实际构造放在其他地方:

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();
    }
}

这真的不是更好。

这篇关于如何在构造函数外调用超级构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆