【问题标题】:How do I call a super constructor outside a constructor?如何在构造函数之外调用超级构造函数?
【发布时间】:2016-07-16 08:23:42
【问题描述】:

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

我不成功的幼稚尝试(导致 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 类是基于原型的继承的语法糖,所以如果这是我会感到惊讶的使用内置语言功能不可行。我似乎无法弄清楚正确的语法。

到目前为止,我最好的感觉就像作弊一样:

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

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

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

【问题讨论】:

  • 是什么阻止您使用标准的class B extends A { constructor() { super(); this.b = 2; }},因为它应该是?
  • 您的“解决方案”实际上是语法错误。
  • @Bergi 我知道我的第一种方法是语法错误,这就是我问的原因。我澄清了我的问题,谢谢。
  • 其实我的意思是第二个。是的,你的第一个 sn-p 也是一个语法错误。
  • 构造函数不包含super() 调用。例如,Babel 就做到了这一点。

标签: javascript class inheritance constructor ecmascript-6


【解决方案1】:

extends 的类的每个构造函数必须包含直接的super(…) 调用。
直接super(…) 调用只能放在构造函数中。真的没有办法解决这个问题。

你真的不应该把类的初始化逻辑放在它的构造函数中。直接正确的解决方案是根本不使用initB

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

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

也就是说,有一种方法可以颠覆“super() 调用必须在构造函数中”的要求。将它放在箭头函数中也很重要!所以你可以这样做

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

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

请答应我永远不要那样做。

另一种模式是根本不调用super(),只要你从构造函数返回一个对象,它就可以工作。这样,您就可以将对象的实际构造放在其他任何地方:

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

其实也好不到哪里去。

【讨论】:

  • "把它放在箭头函数里面也很重要!" --- 是否符合标准? const a = () => { super() }; --- 这也使 babel 变得愚蠢,但是能够避免调用父构造函数看起来具有破坏性:-S
  • 澄清一下,只有在你想使用this时才需要调用super
  • @Oriol 但是babel/repl 怎么样?
  • 这很有趣,但是 babel 从您的第二个示例中生成了损坏的 JS。
  • @Bergi 我认为您正在向后阅读早期错误中的否定,如果没有extends,则禁止super(),但只要您在具有的类中返回显式值extendssuper() 不是必需的。
猜你喜欢
  • 2021-11-23
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 2012-10-27
  • 2011-01-24
  • 1970-01-01
相关资源
最近更新 更多