Node.js自定义Builder类报错:myUser.equals is not a function
TypeError: myUser.equals is not a function 问题分析与解决
咱先直接点出问题的核心:你把createUserObject()返回的新对象覆盖了原来的User实例,导致后续调用equals方法时,对象根本不是User类的实例,自然找不到这个方法。
错误根源拆解
看你的调用代码:
var myUser = new User(); myUser = myUser.createUserObject().withTitle([DATA])...
- 第一行的
myUser确实是User类的实例,拥有equals方法。 - 但第二行调用
createUserObject()后,这个方法返回的是一个全新的字面量对象(里面只有withXXX系列方法),你把这个对象重新赋值给了myUser。 - 此时的
myUser已经和原来的User实例毫无关系,它没有继承User类的任何方法,包括equals,所以调用myUser.equals()就会抛出TypeError。
两种修复方案(附代码)
方案1:修改createUserObject,让它返回当前User实例
把Builder方法直接挂载到当前实例上,而不是返回新对象,这样链式调用后还是原来的User实例,就能正常调用equals了:
module.exports = class User { constructor() { this.title = ''; this.firstName = ''; this.lastName = ''; this.email = ''; this.emailConfirmation = ''; this.password = ''; this.passwordConfirmation = ''; this.addressLine1 = ''; this.addressLine2 = ''; this.town = ''; this.postcode = ''; // 统一属性名,修复原代码的大小写bug this.customerToken = ''; this.businessOwner = ''; this.authToken = ''; this.subscriptionsCount = ''; } equals(jsonObject) { return (jsonObject.title === this.title && jsonObject.firstName === this.firstName && jsonObject.lastName === this.lastName && jsonObject.email === this.email && jsonObject.addressLine1 === this.addressLine1 && jsonObject.town === this.town && jsonObject.postcode === this.postcode) } createUserObject() { // 将Builder方法挂载到当前User实例 this.withTitle = n => { this.title = n; return this }; this.withFirstName = n => { this.firstName = n; return this }; this.withLastName = n => { this.lastName = n; return this }; this.withEMail = n => { this.email = n; return this; }; this.withEMailConfirmation = n => { this.emailConfirmation = n; return this; }; this.withPassword = n => { this.password = n; return this; }; this.withPasswordConfirmation = n => { this.passwordConfirmation = n; return this; }; this.withAddressLine1 = n => { this.addressLine1 = n; return this; }; this.withAddressLine2 = n => { this.addressLine2 = n; return this; }; this.withTown = n => { this.town = n; return this; }; this.withPostCode = n => { this.postcode = n; return this; }; // 修正属性名,和构造函数一致 this.withAuthToken = n => { this.authToken = n; return this; }; this.withBusinessOwner = n => { this.businessOwner = n; return this; }; this.withCustomerToken = n => { this.customerToken = n; return this; }; this.withSubscriptionsCount = n => { this.subscriptionsCount = n; return this; }; return this; // 返回当前User实例 } };
调用时可以简化为:
const myUser = new User().createUserObject() .withTitle([DATA]) .withFirstName([DATA]) .withLastName([DATA]) .withEMail([DATA]) .withAddressLine1([DATA]) .withAddressLine2([DATA]) .withTown([DATA]) .withPostCode([DATA]) .withAuthToken([DATA]) .withBusinessOwner([DATA]) .withCustomerToken([DATA]) .withSubscriptionsCount([DATA]); if(myUser.equals([VALIDATION-DATA])) { // 执行你的业务操作 } else { // 抛出错误或其他逻辑 }
方案2:直接把Builder方法定义在User类原型上(更优雅)
这种方式不需要额外调用createUserObject,实例化后直接就能链式调用属性设置方法,代码更简洁:
module.exports = class User { constructor() { this.title = ''; this.firstName = ''; this.lastName = ''; this.email = ''; this.emailConfirmation = ''; this.password = ''; this.passwordConfirmation = ''; this.addressLine1 = ''; this.addressLine2 = ''; this.town = ''; this.postcode = ''; this.customerToken = ''; this.businessOwner = ''; this.authToken = ''; this.subscriptionsCount = ''; } equals(jsonObject) { return (jsonObject.title === this.title && jsonObject.firstName === this.firstName && jsonObject.lastName === this.lastName && jsonObject.email === this.email && jsonObject.addressLine1 === this.addressLine1 && jsonObject.town === this.town && jsonObject.postcode === this.postcode) } // 直接定义链式设置方法 withTitle(n) { this.title = n; return this; } withFirstName(n) { this.firstName = n; return this; } withLastName(n) { this.lastName = n; return this; } withEMail(n) { this.email = n; return this; } withEMailConfirmation(n) { this.emailConfirmation = n; return this; } withPassword(n) { this.password = n; return this; } withPasswordConfirmation(n) { this.passwordConfirmation = n; return this; } withAddressLine1(n) { this.addressLine1 = n; return this; } withAddressLine2(n) { this.addressLine2 = n; return this; } withTown(n) { this.town = n; return this; } withPostCode(n) { this.postcode = n; return this; } withAuthToken(n) { this.authToken = n; return this; } withBusinessOwner(n) { this.businessOwner = n; return this; } withCustomerToken(n) { this.customerToken = n; return this; } withSubscriptionsCount(n) { this.subscriptionsCount = n; return this; } };
调用代码更清爽:
const myUser = new User() .withTitle([DATA]) .withFirstName([DATA]) // ...其他属性设置 .withSubscriptionsCount([DATA]); if(myUser.equals([VALIDATION-DATA])) { // 业务逻辑 }
额外提醒
原代码里有个容易忽略的bug:构造函数里的属性是postcode,但withPostCode方法里赋值的是this.postCode(大小写不一致),会导致邮编属性无法正确设置,上面的方案已经统一了属性名,记得要避免这种大小写错误。
内容的提问来源于stack exchange,提问作者Raisus
相关产品推荐
相关产品推荐

