Express路由中控制器对象方法this指向undefined问题咨询
Express控制器中this指向undefined的原因及解决方法
核心原因
当你把userController.list作为回调函数传给router.get时,这个方法被单独提取出来执行,丢失了原本指向userController对象的上下文。在ES模块的严格模式下(Node.js默认开启),独立调用的函数内部this会默认指向undefined,这就是你看到console.log(this)输出undefined的根本原因。
三种写法失效的具体原因
1. 对象字面量async方法声明
比如你这样定义:
const userController = { _statusCode: 500, async list(req, res) { console.log(this); // undefined // ...你的代码 } }; export default userController;
当router.get调用list时,相当于直接执行list(req, res),而不是userController.list(req, res),方法和原对象的关联被切断,this自然丢失。
2. 赋值为async function
这种写法本质和第一种一致:
const userController = { _statusCode: 500 }; userController.list = async function(req, res) { console.log(this); // undefined // ...你的代码 }; export default userController;
函数被单独引用后执行,同样丢失了userController的上下文。
3. 赋值为async箭头函数
箭头函数的this是定义时确定的,而非执行时。在ES模块中,顶级作用域的this是undefined,所以当你这样写:
const userController = { _statusCode: 500, list: async (req, res) => { console.log(this); // undefined // ...你的代码 } }; export default userController;
箭头函数定义时的上下文是模块顶级的undefined,所以不管怎么调用,this都不会指向userController。
解决方法
方法1:路由中用箭头函数包裹,手动传递上下文
在路由里通过箭头函数调用控制器方法,保证this指向userController:
import userController from "../controllers/userController.js" router.get("/", isAuth, isAdmin, (req, res, next) => { userController.list(req, res, next); });
方法2:给方法绑定this
在控制器导出前,用bind把list方法的this固定为userController:
const userController = { _statusCode: 500, async list(req, res) { console.log(this); // 现在指向userController // ...你的代码 } }; // 绑定this userController.list = userController.list.bind(userController); export default userController;
方法3:改用类创建控制器实例
如果你的控制器逻辑复杂,用类封装更清晰,实例方法可以通过bind或者箭头函数属性保证this指向:
class UserController { constructor() { this._statusCode = 500; // 绑定方法到实例 this.list = this.list.bind(this); } async list(req, res) { console.log(this); // 指向UserController实例 // ...你的代码 } } export default new UserController();
内容的提问来源于stack exchange,提问作者Amirhossein Hassani
相关产品推荐
相关产品推荐

