如何在传递给super()的异步执行函数中访问父子类实例字段?
解决方案
你的代码报错的根本原因是ES6类继承规范中,super()执行完成前,子类构造函数中的this处于暂时性死区(TDZ),语法层面禁止任何对this的引用,哪怕是封装在后续异步执行的箭头函数中也不允许。
针对你异步回调的场景,有两种常用的可行方案:
方案1:父类回调传入实例参数(改造成本最低)
修改父类逻辑,执行回调时把当前实例作为参数传递,完全规避子类构造阶段的this引用问题:
class Super { constructor(printMyFullName) { this.firstName = 'Fred'; // 调用回调时主动传入当前实例 setTimeout(() => printMyFullName(this), 10000); } }
子类回调直接接收实例参数即可访问所有父类+子类字段:
class Child extends Super { constructor(opts) { // 回调不引用当前作用域的this,不会触发TDZ报错 super((instance) => { console.log('%s %s', instance.firstName, instance.lastName); }); this.lastName = 'Savage'; } }
回调执行时实例已经完成所有初始化,父类和子类的字段都能正常访问。
方案2:拆分回调注册逻辑(结构更合理)
调整父类设计,把异步回调注册从构造函数中拆分出来,符合类设计的单一职责原则:
class Super { constructor() { this.firstName = 'Fred'; } // 单独提供回调注册方法 registerPrintCallback(cb) { setTimeout(() => cb(this), 10000); } }
子类在super()执行完成、自身字段初始化后再注册回调,此时this已经完全可用:
class Child extends Super { constructor(opts) { super(); this.lastName = 'Savage'; // 此时this已完成初始化,可正常引用 this.registerPrintCallback(() => { console.log('%s %s', this.firstName, this.lastName); }); } }
内容的提问来源于stack exchange,提问作者MegaMatt
相关产品推荐
相关产品推荐

