То, как вы используете понятие приватность, не имеет особого смысла. Для лучшего контроля над свойством его делают приватным, а запись значения осуществляется через специальный метод, который называют, если записать при помощи 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 из его определения.