Рассмотрим следующий код:
const defclass = prototype => {
const constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
};
const Person = defclass({
constructor: function Person(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
},
get fullname() {
delete this.fullname; // doesn't delete on instances
return this.fullname = this.firstname + " " + this.lastname;
}
});
const john = new Person("John", "Doe");
const jane = new Person("Jane", "Doe");
console.log(john.fullname); // John Doe
console.log(jane.fullname); // Jane Doe
Это работает, потому что присвоение свойства на this
тенью несуществующий сеттер.
Теперь рассмотрим тот же код, используя классы ES6:
class Person {
constructor(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
get fullname() {
delete this.fullname; // doesn't delete on instances
return this.fullname = this.firstname + " " + this.lastname;
}
}
const john = new Person("John", "Doe");
const jane = new Person("Jane", "Doe");
console.log(john.fullname); // throws an error because there is no setter
console.log(jane.fullname);
Причина этого не объясняется в этом ответе. Это потому, что мы находим свойство в цепочке прототипов и у него нет сеттера. Итак, почему не та же ошибка возникает при использовании обычных прототипов?
Примечание. Вы можете удалить строку с ключевым словом delete
не влияя на поведение кода.
Я получаю ту же ошибку с первым кодом:
const defclass = prototype => {
const constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
};
const Person = defclass({
constructor: function Person(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
},
get fullname() {
"use strict";
// ^^^^^^^^^^^^
return this.fullname = this.firstname + " " + this.lastname;
}
});
const john = new Person("John", "Doe");
const jane = new Person("Jane", "Doe");
console.log(john.fullname); // John Doe
console.log(jane.fullname); // Jane Doe
Это просто код class
в строгом режиме по умолчанию.
В неаккуратном режиме назначение не работает, но игнорируется, а значение правой стороны return
из геттера. .fullname
повторном .fullname
к .fullname
снова будет запущен геттер.