JavaScript类中调用this方法报错:this.generateWallet不是函数
问题根因
问题出在路由配置环节:你将DashboardController.wallet方法直接赋值给路由的handler属性时,已经把方法和原控制器实例的this绑定解绑了。当Express收到请求触发这个处理函数时,函数内部的this不再指向你导出的DashboardController实例,自然找不到挂载在实例上的generateWallet方法。
你之前查阅的回调中正确this指向的内容其实已经覆盖了这个核心原理——只要把对象/类实例的方法单独抽出来当回调参数传递,就会丢失原有上下文,和你用类语法还是普通对象语法没有区别。
另外你现有代码还有一个隐藏bug:generateWallet方法内部直接使用了req对象,但这个方法并没有接收req作为入参,等你修复this问题后会遇到req is not defined的报错,需要一并处理。
可行解决方案
选任意一种即可:
- 方案1:路由注册时显式绑定实例上下文
修改routes/api/dashboard.js的路由配置,用bind把方法的this固定到控制器实例上:
这个方案不需要改动控制器内部逻辑,只需要调整路由定义。const DashboardController = require("../../app/controller/api/dashboard-controller"); const { AuthMiddleware } = require("../../app/middleware/auth"); module.exports = { group: { prefix: "/dashboard", middleware: [AuthMiddleware], }, routes: [ { method: "get", path: "/", handler: DashboardController.index.bind(DashboardController), }, { method: "get", path: "/wallet", handler: DashboardController.wallet.bind(DashboardController), }, ], }; - 方案2:控制器内用类字段+箭头函数固定this
箭头函数没有自身的this,会直接继承定义时所在作用域的this(也就是类实例),修改控制器代码:class DashboardController { wallet = async (req, res) => { let wallet = await UserWalletRepository.find({ user_id: req.authUser.id, }); if (wallet) return res.send(wallet); // 记得把req传给generateWallet let newWallet = await this.generateWallet(req); res.send(newWallet); } generateWallet = async (req) => { let generatedWallet = await WalletService.generateWallet(); let newWallet = await UserWalletRepository.create({ user_id: req.authUser.id, ...generatedWallet, }); return newWallet; } } module.exports = new DashboardController(); - 方案3:路由handler用匿名函数包裹调用
不直接传递方法引用,而是在路由回调里显式通过控制器实例调用对应方法,this会自动指向实例:routes: [ { method: "get", path: "/", handler: (req, res) => DashboardController.index(req, res), }, { method: "get", path: "/wallet", handler: (req, res) => DashboardController.wallet(req, res), }, ]
注意:你之前判断路由代码不会造成影响是错误的——this丢失的时机就是你把方法从实例上拆下来单独赋值给handler的那一刻,和后续函数执行到哪一行没有关系。
内容的提问来源于stack exchange,提问作者hretic
相关产品推荐
相关产品推荐

