В прошлых темах мы использовали класс, свойства и методы которого были досупны извне, и соответственно мы могли к им обратиться в любом месте программы. Например:
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; tom.print(); // Name: Sam Age: -45
С одной стороны, это замечательно, что мы можем использовать функциональность класса в своей программе, обращаться к его свойствам, методам. Но это может быть источником потенциальных проблем. Как видно в примере выше, мы можем изменить имя человека. Но что, если мы не хотим, чтобы в программе можно было менять начальное имя? Также мы можем изменить возраст человека, но изменить его на любое число, которое может предствлять некорректный возраст (например, отрицательный).
Иногда необходимо, чтобы к данным или действиям извне класса нельзя было обратиться, и чтобы к ним можно было обращаться только внутри этого же класса. Или иными словами, сделать свойства и методы класса приватными - доступными только для этого класса. И язык 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; // ! Ошибка - нельзя обратиться к приватному полю tom.print(); // Name: Tom Age: 37
В примере выше определены приватные поля #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); tom.print(); // Name: Tom Age: 37 tom.setAge(22); tom.print(); // Name: Tom Age: 22 tom.setAge(-1234); tom.print(); // Name: Tom Age: 22
В данном случае метод 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); tom.print(); // Name: Tom Age: 37 const bob = new Person("admin", 41); bob.print(); // Name: Undefined Age 41 //let personName = bob.#checkName("admin"); // ! Ошибка - нельзя обратится к приватному методу
В примере выше определен приватный метод #checkName()
, который выполняет условную проверку имени - ели оно не равно "admin", то возвращает переданное значение. (К примеру, мы не хотим,
чтобы имя пользователя было "admin"). И также вне класса мы не можем обратиться к этому методу:
let personName = bob.#checkName("admin"); // ! Ошибка
Как правило, подобные приватные методы используются для выполнения каких-то вспомогательных действий, как, например, валидация в примере выше, и которые нет смысла делать доступнми из вне.