JavaScript继承Socket父类传回调触发super前不可用this错误如何解决
报错的核心原因是:ES6 类继承规则要求子类构造函数中必须先调用super()完成父类初始化后,才能访问this;同时你用类字段语法定义的messageHandler、errorHandler两个箭头函数,初始化时机是在super()执行完成之后才会挂载到this上,因此调用super时传this.xxx必然非法。
最优方案是改用模板方法模式,这是最符合继承设计逻辑的实现,完全不需要通过构造函数传回调:
方案1:模板方法模式(推荐)
直接在基类中定义占位的处理方法,子类重写对应方法实现自定义逻辑即可:
改后基类代码
class SocketBase { constructor() { // 无需再接收回调参数 } // 定义占位方法,强制子类实现(也可以写空实现做降级) messageHandler(x) { throw new Error('子类必须实现 messageHandler 方法') } errorHandler(err) { throw new Error('子类必须实现 errorHandler 方法') } openSocket = async () => { // 原有开启socket逻辑不变 subscribe( (x) => this.messageHandler(x), (err) => this.errorHandler(err), () => console.log("Observer got a complete notification"), ) } }
改后子类代码
class Sub extends SocketBase { constructor(link) { super() // 子类自有参数正常初始化 this.link = link } // 直接重写父类的处理方法即可,支持箭头函数绑定this errorHandler = (err) => { // 子类自定义错误处理逻辑 } messageHandler = (message) => { // 子类自定义消息处理逻辑 } }
这个方案没有多余的封装,完全复用父类的连接逻辑,同时子类只需要关心自己的业务处理,代码整洁符合面向对象设计规范。
备选方案:不改基类的兼容实现
如果你没有权限修改基类的构造函数签名,非要保留基类接收回调的设计,可以在父类中增加初始化方法,子类调用完super之后再传入回调:
// 基类增加init方法 class SocketBase { constructor() {} init(messageHandler, errorHandler) { this.messageHandler = messageHandler this.errorHandler = errorHandler } // 原有openSocket逻辑不变 } // 子类实现 class Sub extends SocketBase { constructor(link) { super() this.link = link // super执行完成后再传入当前实例的处理方法 this.init(this.messageHandler, this.errorHandler) } errorHandler = (err) => {/*逻辑*/} messageHandler = (message) => {/*逻辑*/} }
内容的提问来源于stack exchange,提问作者Jeppe Christensen
相关产品推荐
相关产品推荐

