JavaScript 私有字段

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

JavaScript 私有字段简介

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

例如,以下代码定义了 Circle 类,它包含一个私有字段 radius

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

在这个例子中

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

以下代码创建了 Circle 类的新的实例并计算了它的面积

let circle = new Circle(10);
console.log(circle.area); // 314.1592653589793Code language: JavaScript (javascript)

由于 #radius 是一个私有字段,您只能在 Circle 类内部访问它。换句话说,#radius 字段在 Circle 类之外是不可见的。

使用 getter 和 setter 访问私有字段

以下代码通过添加 radius getter 和 setter 来重新定义 Circle 类,以便访问 #radius 私有字段

class Circle {
  #radius = 0;
  constructor(radius) {
    this.radius = radius; // calling setter
  }
  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;
  }
}Code language: JavaScript (javascript)

工作原理。

  • radius setter 在将参数分配给 #radius 私有字段之前验证参数。如果参数不是正数,radius setter 将抛出错误。
  • radius getter 返回 #radius 私有字段的值。
  • 构造函数调用 radius setter 将参数分配给 #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
  }
}Code language: JavaScript (javascript)

如果您试图在 Cylinder 类中访问 #radius 私有字段,您将得到一个 SyntaxError 错误。

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

要检查对象是否在类内部包含私有字段,您可以使用 in 运算符

fieldName in objectName

例如,以下代码在 Circle 类中添加了 hasRadius() 静态方法,该方法使用 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));
Code language: JavaScript (javascript)

输出

trueCode language: JavaScript (javascript)

静态私有字段

以下示例展示了如何使用静态私有字段

class Circle {
  #radius = 0;
  static #count = 0;
  constructor(radius) {
    this.radius = radius; // calling setter
    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());
Code language: JavaScript (javascript)

工作原理。

首先,在 Circle 类中添加一个私有静态字段 #count,并将它的值初始化为零

static #count = 0;Code language: JavaScript (javascript)

其次,在构造函数中将 #count 增加一

Circle.#count++;Code language: JavaScript (javascript)

第三,定义一个静态方法,该方法返回 #count 私有静态字段的值

static getCount() {
    return Circle.#count;
}Code language: JavaScript (javascript)

最后,创建 Circle 类的三个实例并将 count 值输出到控制台

let circles = [new Circle(10), new Circle(20), new Circle(30)];
console.log(Circle.getCount());
Code language: JavaScript (javascript)

总结

  • 在字段名前添加 # 符号,将其设置为私有字段。
  • 私有字段只能在类内部访问,不能在类外部或子类中访问。
  • 使用 in 运算符检查对象是否包含私有字段。
本教程对您有帮助吗?