类中具有 getter 和 setter 的无限循环

0x6*_*C74 5 javascript ecmascript-6

alert("Hello")

class Dog {

  constructor(name, weight)
  {
    this.name = name;
    this.weight = weight;
  }

  /*
  get name(){
    return this.name;
  }

  set name(value){
    this.name = value;
  }
  */
}

alert("Hello1");

let pies = new Dog("Reksio", 999);

alert("Hello2");
alert(pies.name);
Run Code Online (Sandbox Code Playgroud)

这段代码无需 getter 和 setter 即可完美运行。然而,在取消注释部分后,它奇怪地崩溃了:

Uncaught RangeError: Maximum call stack size exceeded
    at Dog.set name [as name] ((index):44)
    at Dog.set name [as name] ((index):45)
    at Dog.set name [as name] ((index):45)
    at Dog.set name [as name] ((index):45)
    at Dog.set name [as name] ((index):45)
    at Dog.set name [as name] ((index):45)
    at Dog.set name [as name] ((index):45)
    at Dog.set name [as name] ((index):45)
    at Dog.set name [as name] ((index):45)
    at Dog.set name [as name] ((index):45)
Run Code Online (Sandbox Code Playgroud)
  1. 为什么我不能单独使用 getter?
  2. 为什么添加简单的 getter 和 setter 后会像无限递归一样崩溃?
  3. 如何修复 getter 和 setter?

zer*_*298 6

通过让 settername设置成员变量,您将一次又一次地name调用 setter,直到堆栈溢出。name

直接针对您的评论:

我以为设置器仅用于外部调用

实际上没有“内部”或“外部”调用的概念。this我想您将“内部”定义为“来自成员函数内部”或在构造对象所在的位置。不管怎样,事实并非如此。定义 setter 后,任何时候尝试设置属性,无论是“内部”还是“外部”,都会调用 setter。

您必须使用中间变量,例如_name. 否则你将无限递归到设置name

class Foo {
  constructor(name = "") {
    this._name = name;
  }
  set name(newVal) {
    this._name = newVal;
  }
  get name() {
    return this._name;
  }
}

const f = new Foo("foo");
console.log(f.name);
Run Code Online (Sandbox Code Playgroud)

如果你想私有化内部_name成员变量,以便 API 使用者被迫通过name,我很幸运地使用了一个Map对象,该对象将 s 的所有实例的静态引用保存Foo到“私有”变量的对象。它可能不是很有效,但如果隐私比性能更重要,那么它是一个选择。