You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:08:30