为何JavaScript类的密码getter未输出星号掩码反而显示原密码?
问题原因与解决方法
你的代码出现问题是因为两个核心错误:
1. 无限递归问题
你定义的get password()和set password()与类中的password实例属性重名,导致:
- 在getter中调用
this.password.replace(...)时,会反复触发getter自身,陷入无限递归。浏览器为了避免崩溃,会直接返回未处理的原始值(也就是你看到的原密码)。 - 如果密码符合规则,setter里的
this.password = newPassword会反复触发setter,最终导致栈溢出错误。
2. 无独立存储真实密码的变量
你没有专门的变量存储真实密码,所有操作都直接作用于被getter/setter接管的password属性,无法正确生成掩码。
修正后的代码
方案1:使用ES6私有字段(推荐)
私有字段#password只能在类内部访问,彻底避免外部篡改和命名冲突:
class User{ username #password constructor(username, password){ this.username = username this.password = password // 触发setter验证 } get password(){ return this.#password.replace(/./g, '*') } set password(newPassword){ const passwordRegex = /^(?=.*\d)(?=.*[A-Z]).{8,}$/ if(passwordRegex.test(newPassword)){ this.#password = newPassword // 直接赋值私有字段,不触发setter }else{ console.error("Password must be at least 8 characters long and contain at least one number and one uppercase letter") } } } // 测试合法密码 const user = new User('username', 'MyPass1234') console.log(user.password); // 输出********** // 测试非法密码 const invalidUser = new User('test', 'mypassword') // 控制台输出错误提示
方案2:使用约定内部变量(兼容旧环境)
如果环境不支持私有字段,用下划线前缀_password约定为内部变量(虽不是真正私有,但符合社区规范):
class User{ username _password constructor(username, password){ this.username = username this.password = password } get password(){ return this._password.replace(/./g, '*') } set password(newPassword){ const passwordRegex = /^(?=.*\d)(?=.*[A-Z]).{8,}$/ if(passwordRegex.test(newPassword)){ this._password = newPassword }else{ console.error("Password must be at least 8 characters long and contain at least one number and one uppercase letter") } } }
内容的提问来源于stack exchange,提问作者Hrishikesh Tule
相关产品推荐
相关产品推荐

