JavaScript构造函数无法访问自身属性:子类继承基类如何访问字段
解决基类构造函数无法访问子类fields属性的问题
问题原因
在ES6类继承机制中,子类的实例字段初始化操作会在super()调用完成之后执行。当基类BaseModel的构造函数运行时,子类UserModel的fields还未被挂载到实例上,因此this.fields会返回undefined。
解决方案
方案1:将子类fields定义为静态属性
把fields改为子类的静态属性,基类构造函数通过this.constructor.fields访问(this.constructor指向当前实例所属的子类),这样就能在基类构造函数中直接获取到字段配置:
class BaseModel { constructor() { const fields = this.constructor.fields; console.log(fields); fields.map((field) => { field.label = field.label || field.name; }); } } class UserModel extends BaseModel { static fields = [ { name: 'id' }, { name: 'name' }, { name: 'email' }, ]; constructor(name, email) { super(); this.name = name; this.email = email; } } const user = new UserModel('bob', 'me@bob.com'); console.log(user);
方案2:基类提供初始化方法,子类手动调用
基类不直接在构造函数中处理字段,而是单独写一个初始化方法,子类在super()之后调用该方法——此时子类的实例字段已经完成初始化:
class BaseModel { constructor() { // 基类构造函数不处理字段 } initFields() { console.log(this.fields); this.fields.map((field) => { field.label = field.label || field.name; }); } } class UserModel extends BaseModel { fields = [ { name: 'id' }, { name: 'name' }, { name: 'email' }, ]; constructor(name, email) { super(); this.initFields(); // 调用基类初始化方法 this.name = name; this.email = email; } } const user = new UserModel('bob', 'me@bob.com'); console.log(user);
方案3:子类构造函数中传字段给基类
子类提前定义字段,通过super()的参数传递给基类构造函数,避免依赖实例字段的初始化顺序:
class BaseModel { constructor(fields) { console.log(fields); fields.map((field) => { field.label = field.label || field.name; }); this.fields = fields; } } class UserModel extends BaseModel { constructor(name, email) { const fields = [ { name: 'id' }, { name: 'name' }, { name: 'email' }, ]; super(fields); // 先传字段给基类 this.name = name; this.email = email; } } const user = new UserModel('bob', 'me@bob.com'); console.log(user);
最佳实践推荐
优先选择方案1(静态属性)或方案2(手动调用初始化方法),这两种方式符合ES6类的设计规范,代码可读性和可维护性更高。
内容的提问来源于stack exchange,提问作者blented
相关产品推荐
相关产品推荐

