JavaScript Private Fields
Introduction to the JavaScript private fields
ES2022 allows you to define private fields for a class. To define a private field, you prefix the field name with the # sign.
For example, the following defines the Circle class with a private field radius:
class Circle {
#radius;
constructor(value) {
this.#radius = value;
}
get area() {
return Math.PI * Math.pow(this.#radius, 2);
}
}Code language: PHP (php)
In this example:
- First, define the private field
#radiusin the class body. - Second, initialize the
#radiusfield in the constructor with an argument. - Third, calculate the area of the circle by accessing the
#radiusprivate field in the getter method.
The following creates a new instance of the Circle class and calculates its area:
let circle = new Circle(10);
console.log(circle.area); // 314.1592653589793Code language: JavaScript (javascript)
Because the #radius is a private field, you can only access it inside the Circle class. In other words, the #radius field is invisible outside of the Circle class.
Using getter and setter to access private fields
The following redefines the Circle class by adding the radius getter and setter to provide access to the #radius private field:
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;
}
}Code language: PHP (php)
How it works.
- The
radiussetter validates the argument before assigning it to the#radiusprivate field. If the argument is not a positive number, theradiussetter throws an error. - The
radiusgetter returns the value of the#radiusprivate field. - The constructor calls the
radiussetter to assign the argument to the#radiusprivate field.
Private fields and subclasses
Private fields are only accessible inside the class where they’re defined. Also, they’re not accessible from the subclasses. For example, the following defines the Cylinder class that extends the Circle class:
class Cylinder extends Circle {
#height;
constructor(radius, height) {
super(radius);
this.#height = height; // cannot access the #radius of the Circle class here
}
}
Code language: PHP (php)
If you attempt to access the #radius private field in the Cylinder class, you’ll get a SyntaxError.
The in operator: check private fields exist
To check if an object has a private field inside a class, you use the in operator:
fieldName in objectName
For example, the following adds the hasRadius() static method to the Circle class that uses the in operator to check if the circle object has the #radius private field:
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: PHP (php)
Output:
trueCode language: JavaScript (javascript)
Static private fields
The following example shows how to use use a static private field:
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());
Code language: PHP (php)
How it works.
First, add a private static field #count to the Circle class and initialize its value to zero:
static #count = 0;Code language: PHP (php)
Second, increase the #count by one in the constructor:
Circle.#count++;Code language: CSS (css)
Third, define a static method that returns the value of the #count private static field:
static getCount() {
return Circle.#count;
}Code language: PHP (php)
Finally, create three instances of the Circle class and output the count value to the console:
let circles = [new Circle(10), new Circle(20), new Circle(30)];
console.log(Circle.getCount());
Code language: JavaScript (javascript)
Summary
- Prefix the field name with
#sign to make it private. - Private fields are accessible only inside the class, not from outside of the class or subclasses.
- Use the
inoperator to check if an object has a private field.