Summary: in this tutorial, you’ll learn about JavaScript private fields and how to use them effectively.
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: JavaScript (javascript)
In this example:
- First, define the private field
#radius
in the class body. - Second, initialize the
#radius
field in the constructor with an argument. - Third, calculate the area of the circle by accessing the
#radius
private 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.1592653589793
Code 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; // 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)
How it works.
- The
radius
setter validates the argument before assigning it to the#radius
private field. If the argument is not a positive number, theradius
setter throws an error. - The
radius
getter returns the value of the#radius
private field. - The constructor calls the
radius
setter to assign the argument to the#radius
private 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: JavaScript (javascript)
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: JavaScript (javascript)
Output:
true
Code language: JavaScript (javascript)
Static private fields
The following example shows how to use a static private field:
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)
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: JavaScript (javascript)
Second, increase the #count
by one in the constructor:
Circle.#count++;
Code language: JavaScript (javascript)
Third, define a static method that returns the value of the #count
private static field:
static getCount() {
return Circle.#count;
}
Code language: JavaScript (javascript)
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
in
operator to check if an object has a private field.