在本教程中,您将了解 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
类并添加radius
getter 和 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());
怎么运行的。
首先,添加一个私有静态字段 #count
到 Circle
类并将其值初始化为零:
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
运算符检查对象是否存在指定的私有字段。