#javascript
Вопрос:
В чем смысл использования методов получения и установки. Что именно они делают и в чем заключаются преимущества. Я пытался разобраться в них, но я просто не понимаю, что это за подчеркивание, которое используется с помощью вышеуказанных методов. Может кто-нибудь мне это объяснить? Спасибо.
Комментарии:
1. Я боюсь, что здесь не самое подходящее место для этого. Stackoverflow — это не дискуссионный форум. Мы можем помочь людям исправить их ошибки, но мы не должны обсуждать вещи и предоставлять учебные пособия. Я думаю, ты мог бы попробовать на Reddit или что-то в этом роде
Ответ №1:
Свойства средства доступа предоставляют способ вызова функции, когда свойство считывается ( get
) или записывается в ( set
), даже если код, выполняющий это, использует синтаксис доступа к свойствам или присвоения. Вот пример добытчика:
const example = {
get random() {
return Math.random();
}
};
const r = example.random;
console.log(r);
Обратите внимание, что ()
random
в этом примере нет включения, это выглядит как прямой доступ к свойствам данных. Но на самом деле это вызов скрытой функции.
Сеттеры работают точно так же, но когда вы назначаете свойство, а не когда вы его читаете:
const example = {
set something(value) {
console.log(`setter called with ${value}`);
}
};
example.something = 42;
Поскольку они являются вызовами функций, никакое значение не сохраняется, если только функции не хранят его.
Есть несколько причин, по которым вы можете захотеть иметь свойства доступа, а не стандартные свойства данных. Например:
- Проверка: Убедитесь, что заданное значение является допустимым значением для свойства.
- Побочные эффекты: Принятие мер, когда свойство установлено (или прочитано). Например, вы можете зарегистрировать тот факт, что свойство было установлено/получено, или в настройках MVVM/MVC вы можете использовать тот факт, что свойство было изменено, для повторного отображения представления.
Вот пример свойства, для которого можно задать только число:
class Example {
#storedValue = 0;
set value(value) {
const type = typeof value;
if (type !== "number") {
throw new Error(`Value must be of type number, not ${type}`);
}
this.#storedValue = value;
}
get value() {
return this.#storedValue;
}
}
const e = new Example();
e.value = 42;
console.log(e.value); // 42
e.value = "something"; // Throws error
Это использует довольно новую функцию закрытых полей для хранения значения там, где к нему нельзя получить доступ извне класса, поэтому вам нужно пройти через свойство доступа, чтобы добраться до него. Это позволяет классу проверять присвоенные вами значения.
Ответ №2:
Зависит от того, как вы их используете.
Если получатель/установщик просто считывает/записывает значение общедоступного поля (поля по умолчанию являются общедоступными), они, вероятно, на самом деле не нужны. Но когда вы используете закрытые поля (т. Е. Защищаете поля от прямых манипуляций извне класса), вам приходится использовать геттеры и сеттеры для изменения их значения.
Кроме того, у геттеров и сеттеров может быть немного больше логики (санитария, проверки действительности, дополнительные обновления в классе, …). У вас даже могут быть свойства, которые вычисляются только во время выполнения и вообще не поддерживаются полем.
Конечно, вы можете добиться того же с функциями. Но кажется более естественным получить доступ к чему-то, что является свойством объекта, с помощью «синтаксиса поля», чем с помощью функции.
См. Следующий пример: #firstname
и #lastname
являются закрытыми полями класса person, т. е. вы не можете получить доступ p.#firstname
. Таким образом, нам нужны свойства FirstName
и LastName
, чтобы манипулировать ими. Получатель просто возвращает значение соответствующего поля, но установщик также проверяет, является ли имя допустимым (хотя эта конкретная проверка может не иметь большого смысла, это просто пример). Кроме того, у нас есть дополнительный геттер, для FullName
которого возвращается комбинация имени и фамилии.
class Person {
#firstname;
#lastname;
get FirstName() {
return this.#firstname;
}
set FirstName(fn) {
if (!fn || fn.length < 3)
throw "invalid first name"
this.#firstname = fn;
}
get LastName() {
return this.#lastname;
}
set LastName(ln) {
if (!ln || ln.length < 3)
throw "invalid last name"
this.#lastname = ln;
}
get FullName() {
return `${this.#firstname} ${this.#lastname}`;
}
constructor(fn, ln) {
this.#firstname = fn;
this.#lastname = ln;
}
}
let p = new Person("John", "Doe");
//if you uncomment this, you will get a syntax error
//p.#firstname = "Jane";
console.log(p.FirstName);
console.log(p.LastName);
p.FirstName = "Jane";
console.log(p.FullName);
try {
p.LastName = "D."
} catch (e) {
console.log(e);
}