ExpressJS子类回调中继承属性缺失及this未定义问题
嘿,这个问题我之前踩过坑!核心原因是回调函数里的this绑定丢失了——在类的方法里如果直接把普通函数作为Express路由的回调,this就不会指向你的子类实例(类默认是严格模式,所以this会变成undefined)。你用super没用是因为问题根本不是继承失效,而是this的指向错了,下面给你几个靠谱的解决方案:
解决方案1:用箭头函数定义回调方法
箭头函数会自动捕获外层作用域的this,所以把get_aggregate_request写成箭头函数,回调里的this就始终指向CatalogController的实例,就能正常访问_data这些继承属性了:
class CatalogController extends BaseController { // 用箭头函数定义方法,自动绑定this get_aggregate_request = (req, res) => { console.log(this._data); // 能正常访问继承的属性 console.log(this._router); // 也能拿到父类的router对象 res.json({ status: 'success', data: this._data }); }; constructor(app) { super(app); // 直接注册路由即可 this._router.get('/aggregate', this.get_aggregate_request); } }
解决方案2:在构造函数里手动绑定this
如果不想用箭头函数,可以在子类构造函数里把方法绑定到当前实例的this上,这样路由回调的this就不会丢失:
class CatalogController extends BaseController { constructor(app) { super(app); // 关键步骤:把方法绑定到当前实例 this.get_aggregate_request = this.get_aggregate_request.bind(this); // 再注册路由 this._router.get('/aggregate', this.get_aggregate_request); } get_aggregate_request(req, res) { console.log(this._data); // 现在能正常访问了 res.json({ status: 'success', data: this._data }); } }
解决方案3:注册路由时直接绑定
也可以在注册路由的瞬间,用bind把this传入回调,不用修改方法或构造函数的其他部分:
class CatalogController extends BaseController { constructor(app) { super(app); // 注册路由时直接绑定this this._router.get('/aggregate', this.get_aggregate_request.bind(this)); } get_aggregate_request(req, res) { console.log(this._data); // 正常访问继承属性 res.json({ status: 'success', data: this._data }); } }
简单总结下:你遇到的不是继承问题,是JavaScript函数this绑定的经典坑——普通函数作为回调时,会脱离原实例的上下文。上面三个方案任选一个都能解决问题,我个人更推荐第一种箭头函数的写法,代码更简洁直观。
内容的提问来源于stack exchange,提问作者user2932053
相关产品推荐
相关产品推荐

