Приватные поля и методы
До этого момента, мы использовали класс, свойства и методы которого были досупны извне и соответственно мы могли к ним обратиться в любом месте программы:
class Person{
constructor(name, age){
this.name = name;
this.age = age;
}
print(){
console.log(`Name: ${this.name} Age: ${this.age}`);
}
}
const tom = new Person("Tom", 37);
tom.name = "Sam";
tom.age = -45;
// Name: Sam Age: -45
tom.print();
С одной стороны, это замечательно, что мы можем использовать функциональность класса в своей программе, обращаться к его свойствам, методам. Но это может быть источником потенциальных проблем. Как видно в примере выше, мы можем изменить имя человека. Но что, если мы не хотим, чтобы в программе можно было менять начальное имя? Также мы можем изменить возраст человека, но изменить его на любое число, которое может предствлять некорректный возраст (например, отрицательный).
Иногда необходимо, чтобы к данным или действиям извне класса нельзя было обратиться и чтобы к ним можно было обращаться только внутри этого же класса. Или иными словами, сделать свойства и методы класса приватными - доступными только для этого класса. И язык JavaScript предоставляет для этого необходимый инструментарий. Для этого название полей и методов должно начинаться с символа решетки #
.
Приватные поля
Названия приватных полей предваряется символом #
:
class Person{
#name;
#age;
constructor(name, age){
this.#name = name;
this.#age = age;
}
print(){
console.log(`Name: ${this.#name} Age: ${this.#age}`);
}
}
const tom = new Person("Tom", 37);
// Ошибка - нельзя обратиться к приватному полю
tom.#name = "Sam";
// Ошибка - нельзя обратиться к приватному полю
tom.#age = -45;
// Name: Tom Age: 37
tom.print();
В примере выше определены приватные поля #name
и #age
. Установить и получить их значение можно только внури класса Person
. Вне его они не доступны. Поэтому при попытке обратиться к ним через имя объекта, мы получим ошибку:
// Ошибка - нельзя обратиться к приватному полю
tom.#name = "Sam";
// Ошибка - нельзя обратиться к приватному полю
tom.#age = -45;
Если потребуется как-то к ним все-таки обратиться, то мы можем определить для этого методы. Например, выше метод print
() получает их значения и выводит на консоль. Подобным образом можно определить и методы для установки значения:
class Person{
#name;
#age= 1;
constructor(name, age){
this.#name = name;
this.setAge(age);
}
setAge(age){
if (age > 0 && age < 110) this.#age = age;
}
print(){
console.log(`Name: ${this.#name} Age: ${this.#age}`);
}
}
const tom = new Person("Tom", 37);
// Name: Tom Age: 37
tom.print();
tom.setAge(22);
// Name: Tom Age: 22
tom.print();
tom.setAge(-1234);
В данном случае метод setAge
проверяет корректность переданного значения, и если оно корректно, переустанавливает возраст.
Приватные методы
Названия приватных методов также предваряются символом #
:
class Person{
#name = "undefined";
#age = 1;
constructor(name, age){
this.#name = this.#checkName(name);
this.setAge(age);
}
#checkName(name){
if(name!=="admin") return name;
}
setAge(age){
if (age > 0 && age < 110) this.#age = age;
}
print(){
console.log(`Name: ${this.#name} Age: ${this.#age}`);
}
}
const tom = new Person("Tom", 37);
// Name: Tom Age: 37
tom.print();
В примере выше определен приватный метод #checkName()
, который выполняет условную проверку имени - ели оно не равно admin
, то возвращает переданное значение. (К примеру, мы не хотим, чтобы имя пользователя было admin
). И также вне класса мы не можем обратиться к этому методу:
// Ошибка
let personName = bob.#checkName("admin");
Как правило, подобные приватные методы используются для выполнения каких-то вспомогательных действий, как, например, валидация в примере выше, и которые нет смысла делать доступнми из вне.