Для чего нужны геттеры и сеттеры javascript
Перейти к содержимому

Для чего нужны геттеры и сеттеры javascript

  • автор:

Свойства — геттеры и сеттеры

Первый тип это свойства-данные (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 два типа свойств.

  1. Свойства-данные — это обычные свойства, с которыми мы работали в предыдущих статьях.
  2. Свойства-аксессоры — это функции дял присвоения и получения значений объекта. Вне объеккта они выглядят как обычные свойства.

Свойства-аксессоры

Свойства-аксессоры (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 © ООО «Алгоритмы и практика»

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *