В этом руководстве вы узнаете о приватных полях JavaScript и операторе in, о том, как их эффективно использовать.
ES2022 позволяет вам определять частные поля для класса. Чтобы определить личное поле, вы добавляете перед именем поля знак #
.
Например, следующее определяет класс Circle
с закрытым radius
поля:
class Circle {#radius; constructor(value) { this.#radius = value; } get area() { return Math.PI * Math.pow(this.#radius, 2); } }
В этом примере:
- Во-первых, определяем приватное поле
#radius
в теле класса. - Во-вторых, инициализируем поле
#radius
в конструкторе аргументом. - В-третьих, вычислим площадь круга, обратившись к частному полю
#radius
в методе получения.
Следующий код создает новый экземпляр класса Circle
и вычисляет его площадь:
let circle = new Circle(10); console.log(circle.area); // 314.1592653589793
Поскольку #radius
является приватным полем, вы можете получить к нему доступ только внутри класса Circle
. Другими словами, поле #radius
невидимо вне класса Circle
.
Использование геттера и сеттера для доступа к закрытым полям
Следующий код переопределяет класс Circle
, добавляя геттер и сеттер radius
для предоставления доступа к частному полю #radius
:
class Circle {#radius = 0; constructor(radius) { this.radius = radius; } get area() { return Math.PI * Math.pow(this.radius, 2); } set radius(value) { if (typeof value === 'number' & amp; & amp; value & gt; 0) { this.#radius = value; } else { throw 'The radius must be a positive number'; } } get radius() { return this.#radius; } }
Как это работает:
- Установщик
radius
проверяет аргумент, прежде чем назначать его частному полю#radius
. Если аргумент не является положительным числом, установщикradius
выдает ошибку. - Получатель
radius
возвращает значение частного поля#radius
. - Конструктор вызывает установщик
radius
, чтобы присвоить аргумент частному полю#radius
.
Частные поля и подклассы
Закрытые поля доступны только внутри класса, в котором они определены. Кроме того, они недоступны из подклассов. Например, в следующем коде определяется класс Cylinder
, который расширяет класс Circle
:
class Cylinder extends Circle {#height; constructor(radius, height) { super(radius); this.#height = height; // cannot access the #radius of the Circle class here } }
Если вы попытаетесь получить доступ к приватному полю #radius
в классе Cylinder
, вы получите SyntaxError
.
Проверка наличия закрытых полей
Чтобы проверить, есть ли у объекта закрытое поле внутри класса, вы используете оператор in
:
fieldName in objectName
Например, следующий код добавляет статический метод hasRadius()
к классу Circle
, который использует оператор in
для проверки того, имеет ли объект circle
закрытое поле #radius
:
class Circle {#radius = 0; constructor(radius) { this.radius = radius; } get area() { return Math.PI * Math.pow(this.radius, 2); } set radius(value) { if (typeof value === 'number' & amp; & amp; value & gt; 0) { this.#radius = value; } else { throw 'The radius must be a positive number'; } } get radius() { return this.#radius; } static hasRadius(circle) { return#radius in circle; } } let circle = new Circle(10); console.log(Circle.hasRadius(circle));
Выход:
true
Статическое приватное поле
В следующем примере показано, как использовать статическое приватное поле:
class Circle {#radius = 0; static#count = 0; constructor(radius) { this.radius = radius; Circle.#count++; } get area() { return Math.PI * Math.pow(this.radius, 2); } set radius(value) { if (typeof value === 'number' & amp; & amp; value & gt; 0) { this.#radius = value; } else { throw 'The radius must be a positive number'; } } get radius() { return this.#radius; } static hasRadius(circle) { return#radius in circle; } static getCount() { return Circle.#count; } } let circles = [new Circle(10), new Circle(20), new Circle(30)]; console.log(Circle.getCount());
Как это работает:
- Во-первых, добавьте закрытое статическое поле
#count
в классCircle
и инициализируйте его значение нулем:
static #count = 0;
- Во-вторых, увеличьте
#count
на единицу в конструкторе:
Circle.#count++;
- В-третьих, определите статический метод, который возвращает значение закрытого статического поля
#count
:
static getCount() { return Circle.#count; }
- Наконец, создайте три экземпляра класса
Circle
и выведите значениеcount
на консоль:
let circles = [new Circle(10), new Circle(20), new Circle(30)]; console.log(Circle.getCount());
Заключение
- Поставьте перед именем поля знак
#
, чтобы сделать его закрытым. - Частные поля доступны только внутри класса, а не снаружи класса или подклассов.
- Используйте оператор
in
, чтобы проверить, есть ли у объекта закрытое поле.