Свойства — геттеры и сеттеры
Первый тип это свойства-данные (data properties). Мы уже знаем, как работать с ними. Все свойства, которые мы использовали до текущего момента, были свойствами-данными.
Второй тип свойств мы ещё не рассматривали. Это свойства-аксессоры (accessor properties). По своей сути это функции, которые используются для присвоения и получения значения, но во внешнем коде они выглядят как обычные свойства объекта.
Геттеры и сеттеры
Свойства-аксессоры представлены методами: «геттер» – для чтения и «сеттер» – для записи. При литеральном объявлении объекта они обозначаются get и set :
let obj = < get propName() < // геттер, срабатывает при чтении obj.propName >, set propName(value) < // сеттер, срабатывает при записи obj.propName = value >>;
Геттер срабатывает, когда obj.propName читается, сеттер – когда значение присваивается.
Например, у нас есть объект user со свойствами name и surname :
let user = < name: "John", surname: "Smith" >;
А теперь добавим свойство объекта fullName для полного имени, которое в нашем случае «John Smith» . Само собой, мы не хотим дублировать уже имеющуюся информацию, так что реализуем его при помощи аксессора:
let user = < name: "John", surname: "Smith", get fullName() < return `$$`; > >; alert(user.fullName); // John Smith
Снаружи свойство-аксессор выглядит как обычное свойство. В этом и заключается смысл свойств-аксессоров. Мы не вызываем user.fullName как функцию, а читаем как обычное свойство: геттер выполнит всю работу за кулисами.
На данный момент у fullName есть только геттер. Если мы попытаемся назначить user.fullName= , произойдёт ошибка:
let user = < get fullName() < return `. `; >>; user.fullName = "Тест"; // Ошибка (у свойства есть только геттер)
Давайте исправим это, добавив сеттер для user.fullName :
let user = < name: "John", surname: "Smith", get fullName() < return `$$`; >, set fullName(value) < [this.name, this.surname] = value.split(" "); >>; // set fullName запустится с данным значением user.fullName = "Alice Cooper"; alert(user.name); // Alice alert(user.surname); // Cooper
В итоге мы получили «виртуальное» свойство fullName . Его можно прочитать и изменить.
Дескрипторы свойств доступа
Дескрипторы свойств-аксессоров отличаются от «обычных» свойств-данных.
Свойства-аксессоры не имеют value и writable , но взамен предлагают функции get и set .
То есть, дескриптор аксессора может иметь:
- get – функция без аргументов, которая сработает при чтении свойства,
- set – функция, принимающая один аргумент, вызываемая при присвоении свойства,
- enumerable – то же самое, что и для свойств-данных,
- configurable – то же самое, что и для свойств-данных.
Например, для создания аксессора fullName при помощи defineProperty мы можем передать дескриптор с использованием get и set :
let user = < name: "John", surname: "Smith" >; Object.defineProperty(user, 'fullName', < get() < return `$$`; >, set(value) < [this.name, this.surname] = value.split(" "); >>); alert(user.fullName); // John Smith for(let key in user) alert(key); // name, surname
Ещё раз заметим, что свойство объекта может быть либо свойством-аксессором (с методами get/set ), либо свойством-данным (со значением value ).
При попытке указать и get , и value в одном дескрипторе будет ошибка:
// Error: Invalid property descriptor. Object.defineProperty(<>, 'prop', < get() < return 1 >, value: 2 >);
Умные геттеры/сеттеры
Геттеры/сеттеры можно использовать как обёртки над «реальными» значениями свойств, чтобы получить больше контроля над операциями с ними.
Например, если мы хотим запретить устанавливать короткое имя для user , мы можем использовать сеттер name для проверки, а само значение хранить в отдельном свойстве _name :
let user = < get name() < return this._name; >, set name(value) < if (value.length < 4) < alert("Имя слишком короткое, должно быть более 4 символов"); return; >this._name = value; > >; user.name = "Pete"; alert(user.name); // Pete user.name = ""; // Имя слишком короткое.
Таким образом, само имя хранится в _name , доступ к которому производится через геттер и сеттер.
Технически, внешний код всё ещё может получить доступ к имени напрямую с помощью user._name , но существует широко известное соглашение о том, что свойства, которые начинаются с символа «_» , являются внутренними, и к ним не следует обращаться из-за пределов объекта.
Использование для совместимости
У аксессоров есть интересная область применения – они позволяют в любой момент взять «обычное» свойство и изменить его поведение, поменяв на геттер и сеттер.
Например, представим, что мы начали реализовывать объект user , используя свойства-данные имя name и возраст age :
function User(name, age) < this.name = name; this.age = age; >let john = new User("John", 25); alert( john.age ); // 25
…Но рано или поздно всё может измениться. Взамен возраста age мы можем решить хранить дату рождения birthday , потому что так более точно и удобно:
function User(name, birthday) < this.name = name; this.birthday = birthday; >let john = new User("John", new Date(1992, 6, 1));
Что нам делать со старым кодом, который использует свойство age ?
Мы можем попытаться найти все такие места и изменить их, но это отнимает время и может быть невыполнимо, если код используется другими людьми. И кроме того, age – это отличное свойство для user , верно?
Давайте его сохраним.
Добавление геттера для age решит проблему:
function User(name, birthday) < this.name = name; this.birthday = birthday; // возраст рассчитывается из текущей даты и дня рождения Object.defineProperty(this, "age", < get() < let todayYear = new Date().getFullYear(); return todayYear - this.birthday.getFullYear(); >>); > let john = new User("John", new Date(1992, 6, 1)); alert( john.birthday ); // доступен как день рождения alert( john.age ); // . так и возраст
Теперь старый код тоже работает, и у нас есть отличное дополнительное свойство!
Для чего нужны геттеры и сеттеры? [дубликат]
Никак не могу понять для чего применять геттеры и сеттеры. Понятно, что сеттеры задают значение, а геттеры для получение, но главный вопрос — где и для чего это применять? Можете объяснить человеческим языком
Отслеживать
задан 25 янв 2022 в 20:06
113 7 7 бронзовых знаков
При get можно возвращать измененной значение или совершать еще какое событие, к примеру у тебя может быть приватное поле в каком то формате, а через группу get можно получать в различных форматах. Так же и c set можно к примеру добавить проверки и вызывать исключения.
26 янв 2022 в 2:31
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
@Andrey правильно сказал, но также у них есть ещё одна практическая особенность. При их правильном подходе, и использовании private для полей. Мы точно можем сказать, что значения задаются через set и получается через get. А значит если у нас ошибки в коде, их намного легче отлаживать, поскольку мы точно знаем что значения задаются только через них, нам не надо копатся в другом коде
Отслеживать
ответ дан 26 янв 2022 в 5:10
667 3 3 серебряных знака 20 20 бронзовых знаков
-
Важное на Мете
Связанные
Похожие
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.10.27.43697
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
В js геттеры и сеттеры это отдельные функции get, set? Как они работают?
В JS есть особый тип свойств — это свойства-аксессоры. Их особенность в том, что при обращении к этим свойствам вызываются функции, которые выполняют необходимую работу. Все взаимодействия со свойствами сводятся к двум операциям: получение значения из свойства и присваивание нового значения свойству. То есть, чтобы работать со свойством объекта, достаточно описать две операции: операцию получения значения из свойства и операцию сохранения значения в свойство. Это и есть геттеры и сеттеры. Геттер — занимается извлечением значения из свойства, а сеттер — сохранением значения. Для этого в JS есть специальный механизм, в котором ставится get перед геттером и set перед сеттером. Рассмотрим пример, в котором у нас есть пользователь с именем и фамилией:
const user = firstName: 'Ivan', lastName: 'Ivanov', >;
И мы хотим определить третье свойство, которое бы содержало полное имя. Оно зависит от имени и фамилии, поэтому, чтобы не дублировать данные, лучше всего подойдёт геттер:
const user = firstName: 'Ivan', lastName: 'Ivanov', get fullName() return `$this.firstName> $this.lastName>`; >, >; console.log(user.fullName); // => Ivan Ivanov
При обращении к свойству fullName вызывается геттер, который формирует результат и возвращает его. Также мы можем определить сеттер для этого свойства, функция будет обновлять данные о пользователе:
const user = firstName: 'Ivan', lastName: 'Ivanov', get fullName() return `$this.firstName> $this.lastName>`; >, set fullName(fullName) const [first, second] = fullName.split(' '); this.firstName = first; this.lastName = second; >, >; user.fullName = 'Petr Petrov'; console.log(user); // =>
При обновлении свойства, вызывается сеттер, внутри которого происходит вся необходимая работа и сохранение данных, если это необходимо.
Геттеры и сеттеры в JS
В этой статье вы узнаете о том, что такое getters и setters и зачем они нужны в JavaScript.
В прошлых статьях этого раздела мы говорили про объекта и их свойства.
У объектов в JavaScript два типа свойств.
- Свойства-данные — это обычные свойства, с которыми мы работали в предыдущих статьях.
- Свойства-аксессоры — это функции дял присвоения и получения значений объекта. Вне объеккта они выглядят как обычные свойства.
Свойства-аксессоры
Свойства-аксессоры (accessor properties) — это 2 метода, которые получают или устанавливают значение объекта. Для этого используются два ключевых слова:
- get — для геттеров (getters). Геттеры — для чтения, они позволяют получить значение объекта.
- set — для сеттеров (setters). Сеттеры — для записи, они позволяют присваиваивать значения объекта.
Геттеры
Геттеры позволяют получить значение объекта. Рассмотрим на примере:
const student = < // свойство-данные firstName: 'Маша', // свойство-аксессор (геттер) get getName() < return this.firstName; >>; // доступ к свойству-данным console.log(student.firstName); // Вывод: Маша // доступ к свойству-аксессору console.log(student.getName); // Вывод: Маша // если попытаемся вызвать геттер как метод — получим ошибку console.log(student.getName()); // здесь будет ошибка
В этом примере создан геттер getName() . Он позволяет получить доступ к свойству-данным firstName .
get getName()
Примечание. Обратите внимание, что при объявлении геттера используется ключевоео слово get . Оно обязательно.
Сеттеры
Сеттеры позволяют изменять значение объекта. Рассмотрим на примере:
const student = < firstName: 'Маша', // свойство-аксессор (сеттер) set changeName(newName) < this.firstName = newName; >>; console.log(student.firstName); // Вывод: Маша // изменяем свойство объекта с помощью сеттера student.changeName = 'Настя'; console.log(student.firstName); // Вывод: Настя
В этом примере создан сеттер changeName() . Он позволяет получить доступ к свойству-данным firstName .
set changeName(newName)
Примечание. Обратите внимание, что при объявлении сеттера используется ключевоео слово set . Оно обязательно.
Сначала свойство firstName у объекта student — ‘Маша’ . С помощью сеттера мы меняем его на ‘Настя’ .
Примечание. У сеттера обязательно должен быть только один формальный аргумент. Один сеттер изменяет одно свойство.
Object.defineProperty()
Добавлять геттеры и сеттеры в объект можно еще и с помощью метода Object.defineProperty() .
Синтаксис
Object.defineProperty(obj, prop, descriptor)
- Первый аргумент obj — имя объекта.
- Второй аргумент prop — имя свойства.
- Третий аргумент descriptor — объект, описывающий свойство.
Пример
const student = < firstName: 'Маша' >// создаем геттер getName Object.defineProperty(student, "getName", < get : function () < return this.firstName; >>); // создаем сеттер changeName Object.defineProperty(student, "changeName", < set : function (value) < this.firstName = value; >>); console.log(student.firstName); // Вывод: Маша // изменяем свойство firstName student.changeName = 'Настя'; console.log(student.firstName); // Вывод: Настя
СodeСhick.io — простой и эффективный способ изучения программирования.
2023 © ООО «Алгоритмы и практика»