
26.05.2020, 20:49
|
Кандидат Javascript-наук
|
|
Регистрация: 26.12.2017
Сообщений: 123
|
|
Геттеры и сеттеры
Изучаю основы ООП, классы. Столкнулся с проблемой, ответ на который не могу нагуглить (возможно ищу не по тем ключам, так как тема для меня относительно новая). Написал объект с одним приватным свойством и методом для его получения, когда пользователь кликает по одной из двух кнопок выбора пола. Все работает.
let user = {
_sex: '',
setSex: function () {
document.querySelectorAll('.sex-btn').forEach(btn => {
btn.addEventListener('click', () => {
this._sex = btn.value;
});
});
}
};
user.setSex();
Но при попытке создания геттера для класса по аналогии возникли трудности. Не понимаю, как можно сделать установку приватного свойства класса при переборе псевдомассива кнопок или любых других элементов.
class User {
constructor(sex) {
this._sex = sex;
}
set sex(sex) { // откуда будет браться параметр для сеттера не пойму
document.querySelectorAll('.sex-btn').forEach(btn => {
btn.addEventListener('click', () => {
user.sex = btn.value;
});
});
}
get sex() {
return this._sex;
}
}
let user = new User();
user.sex // что сюда передавать тоже не пойму
|
|

26.05.2020, 21:18
|
 |
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 32,781
|
|
DVV,
<input class="sex-btn" type="button" value="m">
<input class="sex-btn" type="button" value="w">
<script>
class User {
constructor(sex) {
this._sex = sex;
document.querySelectorAll('.sex-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log('before', this.sex)
this.sex = btn.value;
console.log('after', this.sex)
});
});
}
set sex(sex) {
this._sex = sex;
}
get sex() {
return this._sex;
}
}
let user = new User('test');
user.sex = 123// что сюда передавать тоже не пойму
</script>
|
|

26.05.2020, 22:24
|
Кандидат Javascript-наук
|
|
Регистрация: 26.12.2017
Сообщений: 123
|
|
Круто. Все работает. Спасибо огромное. Скажите, пожалуйста, то есть всегда в случае псевдомассива в классе надо геттеры и сеттеры в конструкторе писать?
И еще, а в User('test') что означает test? Просто в качестве временного свойства или его можно пустым оставлять?
И зачем тогда
set sex(sex) {
this._sex = sex;
}
Код и без него работает
С одной стороны все вроде понятно, а с другой - что-то я запутался
Последний раз редактировалось DVV, 26.05.2020 в 22:29.
|
|

26.05.2020, 22:39
|
 |
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 32,781
|
|
DVV,
придут люди которые в этом разбираются, может ответят на ваши вопросы более досконально.
Сообщение от DVV
|
а в User('test') что означает test?
|
это обозначает что пол равный test был у user при создании. уберите строку 26. и посмотрите консоль.
Сообщение от DVV
|
И зачем тогда
set sex(sex) {
this._sex = sex;
}
Код и без него работает
|
не сработает изменение кнопками
Сообщение от DVV
|
Скажите, пожалуйста, то есть всегда в случае псевдомассива в классе надо геттеры и сеттеры в конструкторе писать?
|
не осилил.
Последний раз редактировалось рони, 26.05.2020 в 22:42.
|
|

26.05.2020, 22:54
|
 |
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от DVV
|
Написал объект с одним приватным свойством
|
Почему вы решили, что добавление знака «_» в начало имени свойства делает его приватным?
Его совершенно спокойно можно читать и изменять. К вашим примерам из первого сообщения...
user._sex = "와";
console.log(user._sex); // выводит "와"
Конструкции вида...
set sex(sex) {
this._sex = sex;
}
get sex() {
return this._sex;
}
могут быть заменены на
sex = "";
или
this.sex = "";
в конструкторе...
<input class="sex-btn" type="button" value="m">
<input class="sex-btn" type="button" value="w">
<script>
class User {
constructor(sex) {
this.sex = sex;
document.querySelectorAll('.sex-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log('before', this.sex)
this.sex = btn.value;
console.log('after', this.sex)
});
});
}
}
let user = new User('test');
user.sex = 123;
</script>
|
|

27.05.2020, 00:44
|
 |
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
То, как вы используете понятие приватность, не имеет особого смысла. Для лучшего контроля над свойством его делают приватным, а запись значения осуществляется через специальный метод, который называют, если записать при помощи IPA, [ˈsɛɾəɹ] (setter method) и чтение значения осуществляется через специальный метод, который называют [ˈkɛɾəɹ] или [ˈɡɛɾəɹ] (getter method).
При помощи приватного свойства...
<input class="sex-btn" type="button" value="m">
<input class="sex-btn" type="button" value="f">
<script>
class User {
#sex = null;
constructor(sex) {
this.sex = sex;
document.querySelectorAll('.sex-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log('before', this.sex)
this.sex = btn.value;
console.log('after', this.sex)
});
});
}
set sex(sex) {
if(sex !== "m" && sex !== "f")
throw new Error(`The provided value '${sex}' is not a valid enum value of type UserSex—use 'm' or 'f'.`);
this.#sex = sex;
}
get sex() {
return this.#sex;
}
}
let user = new User('m'); // неправильные значения типа test будут вызывать исключение
user.sex = 123;
</script>
При помощи ассоциативного массива... (подойдет для браузеров, где не поддерживаются приватные свойства)
<input class="sex-btn" type="button" value="m">
<input class="sex-btn" type="button" value="f">
<script>
const User = (() => {
const userSex = new WeakMap();
return class User {
constructor(sex) {
this.sex = sex;
document.querySelectorAll('.sex-btn').forEach(btn => {
btn.addEventListener('click', () => {
console.log('before', this.sex)
this.sex = btn.value;
console.log('after', this.sex)
});
});
}
set sex(sex) {
if(sex !== "m" && sex !== "f")
throw new Error(`The provided value '${sex}' is not a valid enum value of type UserSex—use 'm' or 'f'.`);
userSex.set(this, sex);
}
get sex() {
return userSex.get(this);
}
}
})();
let user = new User('m');
user.sex = 123;
</script>
Теперь в поле sex хранится всегда правильное значение — либо 'm', либо 'f'.
Поскольку класс User похож на модель, то скорей всего вам нужно вынести работу с DOM из его определения.
Последний раз редактировалось Malleys, 27.05.2020 в 00:59.
|
|

27.05.2020, 12:50
|
Кандидат Javascript-наук
|
|
Регистрация: 26.12.2017
Сообщений: 123
|
|
Про геттеры и сеттеры я знаю, но гдя я только не читал про них. Везде даны простейшие примеры, которые зачастую с одного ресурса учебного копипастятся другими. Ничего подобного с псевдомассивами я нигде не нашел. Был бы очень благодарен, если подскажите ресурсы, где можно об этом подробно почитать.
А зачем нужна эта строка и именно знак #? #sex = null;
Кроме того, попробовал закомментировать геттер и сеттер в первом примере с 19 по 28 строку. Все работает и без них.
|
|

27.05.2020, 13:39
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,608
|
|
Сообщение от DVV
|
подскажите ресурсы
|
В меню есть ссылка на Учебник, там есть всё.
|
|

27.05.2020, 14:07
|
 |
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от DVV
|
Кроме того, попробовал закомментировать геттер и сеттер в первом примере с 19 по 28 строку. Все работает и без них.
|
Когда удалили, то изчесли приватность и проверки.
Сообщение от DVV
|
А зачем нужна эта строка и именно знак #? #sex = null;
|
Например для того, чтобы хранить значение, которое устанавливается через setter. Свойство, которое начинается на # является реально приватным, т. е. его невозможно прочитать вне определения класса.
Последний раз редактировалось Malleys, 27.05.2020 в 14:12.
|
|

27.05.2020, 16:20
|
Кандидат Javascript-наук
|
|
Регистрация: 26.12.2017
Сообщений: 123
|
|
Понял. Буду разбираться дальше в ООП. Спасибо)))
|
|
|
|