You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

子类通过父类构造函数赋值属性后为何为undefined?如何解决?

问题原因分析

你遇到的问题核心在于类公共字段的初始化时机:

当你在B类里声明b;时,这是一个ECMAScript类的公共字段。在实例化子类B的过程中,代码执行顺序如下:

  1. 进入B的构造函数,打印1,调用super()
  2. 执行A的构造函数,打印2,调用this.inv()——此时因为原型链的关系,this指向B的实例,所以调用的是B类重写的inv方法
  3. 执行B的inv方法:
    • 打印3,调用super.inv()执行A的inv,打印4并给this.a赋值为a value
    • 回到B的inv,打印5,给this.b赋值为b value,此时打印this.b确实是b value
  4. 关键步骤:当super()执行完成后,JavaScript会自动初始化B类的公共字段b,将其设置为undefined,直接覆盖了刚才在inv里给this.b赋的值
  5. 最后打印b.a(不受影响,因为A类的a字段在super.inv()里赋值后,A的构造函数执行完没有后续的字段初始化覆盖它),b.b就变成了undefined
解决方案

这里提供几种可行的解决方式:

方式一:移除子类的公共字段声明

如果不需要提前声明b字段(JavaScript允许动态添加属性),直接删掉B类里的b;即可:

class A {
    a;

    constructor() { console.log(2); this.inv(); }

    inv() { console.log(4); this.a = "a value"; }
}

class B extends A {
    // 删掉这里的b;
    constructor() { console.log(1); super(); }

    inv() {
        console.log(3);
        super.inv();
        console.log(5);
        this.b = "b value";
        console.log(this.b);
        console.log(this.constructor === B);
    }
}

const b = new B();
console.log(b.a); // a value
console.log(b.b); // b value

方式二:将子类字段赋值移到构造函数中

把this.b的赋值逻辑放到B的构造函数里,在super()之后执行,这样就不会被字段初始化覆盖:

class A {
    a;

    constructor() { console.log(2); this.inv(); }

    inv() { console.log(4); this.a = "a value"; }
}

class B extends A {
    b;

    constructor() { 
        console.log(1); 
        super(); 
        // 在这里赋值
        this.b = "b value";
    }

    inv() {
        console.log(3);
        super.inv();
        console.log(5);
        console.log(this.constructor === B);
    }
}

const b = new B();
console.log(b.a); // a value
console.log(b.b); // b value

方式三:使用私有字段(如果需要字段封装)

如果需要明确字段的存在且希望封装,可以使用私有字段#b,此时需要在构造函数里初始化,不会被自动覆盖:

class A {
    a;

    constructor() { console.log(2); this.inv(); }

    inv() { console.log(4); this.a = "a value"; }
}

class B extends A {
    #b; // 私有字段

    constructor() { 
        console.log(1); 
        super(); 
        this.#b = "b value";
    }

    inv() {
        console.log(3);
        super.inv();
        console.log(5);
        console.log(this.constructor === B);
    }

    // 提供getter访问私有字段
    get b() {
        return this.#b;
    }
}

const b = new B();
console.log(b.a); // a value
console.log(b.b); // b value

内容的提问来源于stack exchange,提问作者leopik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:12:39