JavaScript: ошибка при создании объекта из-за имени свойства

у меня такой вопрос по JavaScript:

Вот код класса User:

class User {
  constructor(name) {
    this.name = name;
  }

  get name() {
    return this.name;
  }

  set name(value) {
    this.name = value + '!';
  }
}

let user = new User('Username');
console.log(user);

При попытке создания объекта new User('Username') происходит переполнение стека вызовов (Uncaught RangeError: Maximum call stack size exceeded) и объект не создается. Если изменить имя переменной, в которую записывает значение сеттер, то все будет в порядке:

 // Так будет работать

  set name(value) {
    this._name = value + '!'; // this._name вместо this.name
  }

Вопрос в том, почему это не работало в начальном варианте. Я приведу последовательность действий, поправьте меня там, где я ошибаюсь:

  1. let user = new User('Username'); вызывается конструктор класса, создается пустой объект, на него теперь ссылается this.
  2. this.name = name; строка в конструкторе пытается записать свойство name, но т.к. это не простое свойство, а свойство-аксессор, то из прототипа создаваемого объекта this.proto вызывается сеттер.
  3. this.name = value + '!'; на этой строке из сеттера отладчик в гугл-хром зацикливается. При этом видно, что к переменной value при каждой новой итерации добавляется еще один восклицательный знак (Username!!!!!!!!!!!!!!!!! - до бесконечности).

Так что же все-таки происходит в пункте 3? Или ошибка закралась еще раньше?


Ответы (1 шт):

Автор решения: Igor

Сетер вызывает сетер вызывает сетер ...

Гетер и сетер должны обращаться к полю, а не к свойству.

class User {
  constructor(name) {
    this.name = name;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    this._name = value + '!';
  }
}

let user = new User('Username');
console.log(user);


Представьте, что вместо set name(value) у Вас есть функция setName:

function setName(value) { 
  this.setName(value + "!"); 
}
→ Ссылка