Node.js ES6 Class在Express.js中无法调用内部类方法的问题
嘿,你遇到的这个问题其实是JavaScript中this指向的经典陷阱,尤其是在把类方法作为回调函数传递时很容易踩坑。我来逐个解答你的疑问,再给你可行的解决办法:
1. 原模式为何在Express中不生效?
核心原因是函数调用时的执行上下文(this的指向)变了。当你直接调用users.update()时,this指向的是Users类的实例,所以能正常找到verifyUserIdentity方法;但当你把user.update作为回调传给app.post后,Express在处理请求时会调用这个函数,此时this的指向不再是你的Users实例,而是Express内部的对象(比如请求对象req或者app本身),导致this.verifyUserIdentity是undefined——你说没报错,可能是Node/Express的错误捕获机制没把这个错误抛到控制台,或者你没注意到(实际会抛出TypeError: this.verifyUserIdentity is not a function,可以仔细检查一下日志)。
2. 是否因回调导致this指向异常?
完全正确!这就是问题的本质。当你传递user.update时,你只是传递了一个函数的引用,并没有把它和Users实例绑定在一起。函数的this指向是在调用时决定的,而不是定义时,所以Express调用它时,this就指向了Express的上下文,而不是你的实例。
3. 与Node v8.9.0有关吗?
关系不大。这个this指向的规则是JavaScript的核心特性,不管哪个支持ES6类的Node版本(v6+都支持)都会存在这个问题。Node v8.9.0完全兼容ES6类,所以不是版本的锅。
4. 我的实现方式是否完全错误?
当然不是!你的思路没问题,只是没处理好this的绑定问题,这是很多刚接触ES6类和回调的开发者都会遇到的坑,只要调整一下绑定方式就能正常工作。
可行的解决方案
这里有三种常用的方法来解决这个this指向问题:
方法1:用箭头函数定义类方法
箭头函数的this是词法作用域,会绑定到类的实例上,不会被调用上下文改变:
class Users { // 用箭头函数定义update方法 update = (req, res) => { console.log('updating...'); this.verifyUserIdentity(req, res); // 记得传递req和res参数 } verifyUserIdentity = (req, res) => { console.log('verify'); } } module.exports = new Users;
方法2:传递回调时绑定this
在把update传给app.post时,用bind方法把this绑定到Users实例:
// 绑定this到user实例 app.post('/api/v1/user/update', urlencodedParser, user.update.bind(user));
方法3:在构造函数中绑定this
在类的构造函数里提前把方法的this绑定到实例:
class Users { constructor() { // 绑定this到实例 this.update = this.update.bind(this); this.verifyUserIdentity = this.verifyUserIdentity.bind(this); } update(req, res) { console.log('updating...'); this.verifyUserIdentity(req, res); } verifyUserIdentity(req, res) { console.log('verify'); } } module.exports = new Users;
另外要注意:你的原代码中update调用verifyUserIdentity时没有传递req和res参数,即使this指向正确,verifyUserIdentity里的req和res也会是undefined,记得加上参数传递哦!
内容的提问来源于stack exchange,提问作者Lionel Morrison

