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

两个仅属性命名不同的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属性。

  • 在错误的类实现中:

    1. getter无限递归:get name()里返回this.name,这会再次调用get name(),形成无限递归调用,直到调用栈耗尽。
    2. setter无限递归:set name(value)里执行this.name = value,这会再次调用set name(),同样陷入无限递归。
  • 在正确的类实现中:
    使用this._name存储数据,_name是普通的数据属性,访问或赋值它不会触发任何getter/setter,因此不会产生递归,逻辑可以正常执行。

内容的提问来源于stack exchange,提问作者Yannick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:34:55