Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 26.05.2020, 20:49
DVV DVV вне форума
Кандидат Javascript-наук
Отправить личное сообщение для DVV Посмотреть профиль Найти все сообщения от DVV
 
Регистрация: 26.12.2017
Сообщений: 125

Геттеры и сеттеры
Изучаю основы ООП, классы. Столкнулся с проблемой, ответ на который не могу нагуглить (возможно ищу не по тем ключам, так как тема для меня относительно новая). Написал объект с одним приватным свойством и методом для его получения, когда пользователь кликает по одной из двух кнопок выбора пола. Все работает.

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 // что сюда передавать тоже не пойму
Ответить с цитированием
  #2 (permalink)  
Старый 26.05.2020, 21:18
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,109

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>
Ответить с цитированием
  #3 (permalink)  
Старый 26.05.2020, 22:24
DVV DVV вне форума
Кандидат Javascript-наук
Отправить личное сообщение для DVV Посмотреть профиль Найти все сообщения от DVV
 
Регистрация: 26.12.2017
Сообщений: 125

Круто. Все работает. Спасибо огромное. Скажите, пожалуйста, то есть всегда в случае псевдомассива в классе надо геттеры и сеттеры в конструкторе писать?
И еще, а в User('test') что означает test? Просто в качестве временного свойства или его можно пустым оставлять?
И зачем тогда
set sex(sex) {
this._sex = sex;
}
Код и без него работает
С одной стороны все вроде понятно, а с другой - что-то я запутался

Последний раз редактировалось DVV, 26.05.2020 в 22:29.
Ответить с цитированием
  #4 (permalink)  
Старый 26.05.2020, 22:39
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,109

DVV,
придут люди которые в этом разбираются, может ответят на ваши вопросы более досконально.
Сообщение от DVV
а в User('test') что означает test?
это обозначает что пол равный test был у user при создании. уберите строку 26. и посмотрите консоль.
Сообщение от DVV
И зачем тогда
set sex(sex) {
this._sex = sex;
}
Код и без него работает
не сработает изменение кнопками
Сообщение от DVV
Скажите, пожалуйста, то есть всегда в случае псевдомассива в классе надо геттеры и сеттеры в конструкторе писать?
не осилил.

Последний раз редактировалось рони, 26.05.2020 в 22:42.
Ответить с цитированием
  #5 (permalink)  
Старый 26.05.2020, 22:54
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 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>
Ответить с цитированием
  #6 (permalink)  
Старый 27.05.2020, 00:44
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 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.
Ответить с цитированием
  #7 (permalink)  
Старый 27.05.2020, 12:50
DVV DVV вне форума
Кандидат Javascript-наук
Отправить личное сообщение для DVV Посмотреть профиль Найти все сообщения от DVV
 
Регистрация: 26.12.2017
Сообщений: 125

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

Сообщение от DVV
Кроме того, попробовал закомментировать геттер и сеттер в первом примере с 19 по 28 строку. Все работает и без них.
Когда удалили, то изчесли приватность и проверки.

Сообщение от DVV
А зачем нужна эта строка и именно знак #? #sex = null;
Например для того, чтобы хранить значение, которое устанавливается через setter. Свойство, которое начинается на # является реально приватным, т. е. его невозможно прочитать вне определения класса.

Последний раз редактировалось Malleys, 27.05.2020 в 14:12.
Ответить с цитированием
  #9 (permalink)  
Старый 27.05.2020, 16:20
DVV DVV вне форума
Кандидат Javascript-наук
Отправить личное сообщение для DVV Посмотреть профиль Найти все сообщения от DVV
 
Регистрация: 26.12.2017
Сообщений: 125

Понял. Буду разбираться дальше в ООП. Спасибо)))
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
window.getSelection() .. геттеры? Не, не слышали.. danik.js Оффтопик 16 13.12.2013 12:26