Błąd przy deklaracji getterów i setterów w definicji klasy

0

Hej,
właśnie robię kurs JavaScript. Jestem przy getterach i setterach (http://javascript.info/class) Natrafilem tam na przyklad:

class User {

  constructor(name) {
    // invokes the setter
    this.name = name;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    if (value.length < 4) {
      alert("Name is too short.");
      return;
    }
    this._name = value;
  }

}

let user = new User("John");
alert(user.name); // John

user = new User(""); // Name is too short.

Kiedy sam "przepisałem" kod do swojego edytora (w ramach nauki), dostaje błąd Uncaught RangeError: Maximum call stack size exceeded at User.set name [as name] (<anonymous>:17:15)
W swoim przykładzie zmieniłem niechcący _name przy deklaracji gettera i settera na wersje bez podkreślenia jak poniżej:

class User {

  constructor(name) {
    // invokes the setter
    this.name = name;
  }

  get name() {
    return this.name;
  }

  set name(value) {
    if (value.length < 4) {
      alert("Name is too short.");
      return;
    }
    this.name = value;
  }

}

let user = new User("John");
alert(user.name); // John

user = new User(""); // Name is too short.

Skąd ten błąd? Skąd w "oryginalnym" kodzie wzięła się zmienna _name przy deklaracji gettera i settera skoro nie ma jej w konstruktorze klasy (this.name) a nie (this._name)(?)?
Poszperałem trochę w MDN n.t TypeError (który wyskakiwał przy trochę innej "konfiguracji") ale nadal nie mogę zrozumieć w czym leży problem.

Dziękuję z góry za pomoc.

2

Wywołując this.name = value znowu odpalasz tą metodę set name i tak w kółko tj. rekurencja nieskończona ;)

0

Dobra, ale w deklaracji klasy ustawiam właściwość o nazwie name (którą mają modyfikować gettery i settery(?)) (definicja this.name), więc jakim cudem odwołuje się sama do siebie skoro powinna pobierać albo ustawać tę właściwość. Zachodzi tutaj jakaś zbieżność nazw której nie mogę zrozumieć. Skąd się wzięły właściwośći z podkreśleniem w definicjach getterów i setterów?

Cytat z MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get:

Note the following when working with the get syntax:

It can have an identifier which is either a number or a string;
It must have exactly zero parameters (see Incompatible ES5 change: literal getter and setter functions must now have exactly zero or one arguments for more information);
It must not appear in an object literal with another get or with a data entry for the same property ({ get x() { }, get x() { } } and { x: ..., get x() { } } are forbidden).

2

Skąd w "oryginalnym" kodzie wzięła się zmienna _name przy deklaracji gettera i settera skoro nie ma jej w konstruktorze klasy?

W JavaScripcie nie ma obowiązku deklarowania wszystkich pól w konstruktorze - każda metoda może modyfikować, dodawać oraz usuwać wszystkie pola; oryginalny kod opierał się o to, że setter oraz getter wykorzystują pod spodem "prywatne" pole o nazwie _name, o którym użytkownik nie wie.

Rekurencja staje się oczywista, gdy tylko zamienisz setter wprost na funkcję:

setName(value) {
  if (value.length < 4) {
    alert("Name is too short.");
    return;
  }
  this.setName(value);
}

Skąd się wzięły właściwośći z podkreśleniem w definicjach getterów i setterów?

To taka konwencja - równie dobrze zamiast _name mógłbyś mieć name__, $name, prywatnaNAZWA albo cokolwiek innego, co jest różne od oryginalnej nazwy pola (tj. od name).

1 użytkowników online, w tym zalogowanych: 0, gości: 1