两个仅属性命名不同的User类为何一个触发栈溢出错误?
为什么直接使用this.name的getter/setter会导致栈溢出?
我定义了两个几乎完全相同的User类,唯一区别在于:其中一个类的getter和setter使用this._name存储数据,另一个则直接使用this.name。运行后,后者触发了RangeError: 超出最大调用栈大小错误。请问这两个类的差异为何会导致该栈溢出错误?
正确运行的类代码
class User { constructor(name) { // 调用setter this.name = name; } get name() { return this._name; } set name(value) { if (value.length < 4) { console.log("Name is too short."); return; } this._name = value; } } let user = new User("John"); console.log(user.name); // John user = new User(""); // Name is too short.
触发错误的类代码
class User { constructor(name) { // 调用setter this.name = name; } get name() { return this.name; } set name(value) { if (value.length < 4) { console.log("Name is too short."); return; } this.name = value; } } let user = new User("John"); console.log(user.name); // John user = new User(""); // Name is too short.
错误原因解析
当你在类中定义了get name()和set name()方法后,JavaScript会把name识别为访问器属性,而非普通数据属性。此时任何对this.name的访问或赋值操作,都会自动触发对应的getter或setter方法,而不是直接操作实例上的name属性。
在错误的类实现中:
- getter无限递归:
get name()里返回this.name,这会再次调用get name(),形成无限递归调用,直到调用栈耗尽。 - setter无限递归:
set name(value)里执行this.name = value,这会再次调用set name(),同样陷入无限递归。
- getter无限递归:
在正确的类实现中:
使用this._name存储数据,_name是普通的数据属性,访问或赋值它不会触发任何getter/setter,因此不会产生递归,逻辑可以正常执行。
内容的提问来源于stack exchange,提问作者Yannick
相关产品推荐
相关产品推荐

