myfreax

JavaScript 私有字段

您将了解 JavaScript 私有字段以及如何有效地使用它们

JavaScript 私有字段
JavaScript 私有字段

在本教程中,您将了解 JavaScript 私有字段以及如何有效地使用它们。

JavaScript 私有字段介绍

ES2022 允许您为定义私有字段。要定义私有字段,请在字段名称前加上符号 #

例如,以下定义 Circle 类具有私有字段 radius

class Circle {
  #radius;
  constructor(value) {
    this.#radius = value;
  }
  get area() {
    return Math.PI * Math.pow(this.#radius, 2);
  }
}

在这个例子中:

  • 首先,在类主体中定义私有字段  #radius
  • 其次,在构造函数初始化的字段 #radius
  • 第三,通过 area 的 getter 方法访问私有字段 #radius 来计算圆的面积。

下面创建一个Circle类的实例并计算它的面积:

let circle = new Circle(10);
console.log(circle.area); // 314.1592653589793

因为 #radius 是私有字段,所以只能在 Circle 类内部访问。换句话说,#radius字段在 Circle 类之外是不可见的。

使用 getter 和 setter 访问私有字段

下面重新定义 Circle 类并添加radiusgetter 和 setter 来以提供对#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' && value > 0) {
      this.#radius = value;
    } else {
      throw 'The radius must be a positive number';
    }
  }
  get radius() {
    return this.#radius;
  }
}

怎么运行的。

  • radius setter 在将参数分配给私有字段 #radius 之前验证参数。如果参数不是正数,radius setter 会抛出错误。
  • radius getter 返回私有字段 #radius 的值。
  • 构造函数调用radius setter 将参数分配给 #radius 私有字段。

私有字段和子类

私有字段只能在定义它们的类访问。此外,它们不能从子类访问。例如,下面定义Cylinder 类,Circle 扩展Cylinder

class Cylinder extends Circle {
  #height;
  constructor(radius, height) {
    super(radius);
    this.#height = height;

    // 不能访问 #radius 在 Circle 类
  }
}

如果您尝试访问 Cylinder 类的私有字段 #radius ,您将获得一个 SyntaxError.

运算符 in 检查私有字段是否存在

要检查一个对象是否存在私有字段在类,您可以使用 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' && value > 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' && value > 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());

怎么运行的。

首先,添加一个私有静态字段 #countCircle 类并将其值初始化为零:

static #count = 0;

其次,在构造函数使 #count 增加 1:

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 运算符检查对象是否存在指定的私有字段。

相关文章

内容导航