Приватные поля в JavaScript и оператор in

В этом руководстве вы узнаете о приватных полях 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, чтобы проверить, есть ли у объекта закрытое поле.
Рейтинг
( Пока оценок нет )
Александр Русаков / автор статьи
Программист, разработчик, 12 лет опыта работы в крупных компаниях. Быстро освоил typescript, делюсь своими знаниями на страницах этого сайта.
Загрузка ...
JavaScript и TypeScript