В этом руководстве вы узнаете о приватных полях 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, чтобы проверить, есть ли у объекта закрытое поле.
