无法通过 Babel 的 transform-class-properties 在父 class 构造函数中使用子 class' 属性

Cannot use child class' properties within parent class constructor via Babel's transform-class-properties

当通过 Babel 的 'transform-class-properties' 插件扩展父 class 并声明子 class' 属性时,子 class 的任何 class 属性都是无法通过父 class' 构造方法访问。

class One {

    internal = 1;

    constructor() {
        console.log('constructor internal', this.internal);
    }

}

class Two extends One {

    internal = 2;

}

new Two();

在上面的示例中,'constructor internal 1' 将输出到控制台。当查看编译后的代码时,原因很明显,首先执行父 class,然后将生成的对象与子 class.

集成

抱歉,如果这是设计使然,但它让我感到困惑,因为以下代码在非构造函数方法中以我期望的方式工作(因此 boot() 方法引用子 class''internal' 属性 值):

class One {

    internal = 1;

    constructor() {
        console.log('constructor internal', this.internal);
    }

    boot() {
        console.log('boot internal', this.internal);
    }

}

class Two extends One {

    internal = 2;

    constructor() {
            super();

            this.boot();
    }

}

new Two();

因此,即使调用在父 class 上声明的方法,它也会继承子 class 的属性。这只是构造函数方法似乎没有按预期运行(至少对我而言 - 再次,如果这被错误地解释,我们深表歉意,但相关的 Babel 页面上没有列出任何警告。)

谢谢。

loganfsmyth 在这里非常清楚地回答了我的问题:https://phabricator.babeljs.io/T7567(谢谢!)

This is indeed expected behavior. Babel's implementation is a little incorrect because in a perfect world this would also throw an error, because you shouldn't have the same property defined in a parent and a child, but we don't do that right at the moment.

Class properties are initialized when:

  • For base classes, before the constructor executes

  • For child classes, at the end of super()

and when a given constructor initializes it's bindings, it uses that classes bindings, it doesn't know of anything in child classes. That means your One class knows the value should be 1, so that's what it sets.

我认为这是自然的。如果你想覆盖父 class 的 属性 初始值,你应该在派生的 class 的构造函数中进行。

class Two extends One {

    constructor() {
        // Call parent constructor.
        super();
        // Override here.
        this.internal = 2;
    }

}

希望对您有所帮助。快乐编码 (: