Class fields and class methods are public by default.
It is common you may want to make your class fields private. If you come from a Java background, you may achieve this with the private
keyword inside of a Java class definition. JavaScript has lacked such a feature since its inception.
Article Sections
How to create a private class field
As of ES2022, you can define private fields for a class using #
sign prefixed to the identifiers. You can access private fields from the class constructor within the class declaration.
For example, the following defines the Circle
class with a private field radius
:
class Circle {
// private field
#radius;
constructor(value) {
// You can access private field from constructor
this.#radius = value;
}
get area() {
return Math.PI * Math.pow(this.#radius, 2);
}
}
From the above example,
- We declare private field
#radius
in the body of the class - We initialize the
#radius
field in the constructor with an argument. - We 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:
const circle = new Circle(10);
console.log(circle.area); // 314.1592653589793
Now that 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.
Trying to access the private field outside of the class will generate a syntax error:
console.log(circle.#privateField); // Syntax error
Inheritance
Like public fields, private fields are added at construction time in a base class, or at the point where super()
is invoked in a subclass. But trying to access Private field from a subclass will result in SyntaxError
. Private fields are only accessible in the enclosing class (class where they’re defined). For example, the following defines the Cylinder
class that extends the Circle
class:
class Cylinder extends Circle {
#height;
cRadius;
constructor(radius, height) {
super(radius);
this.#height = height;
// cannot access the #radius of the Circle class here
this.cRadius = this.#radius // Syntax Error
}
}
If you attempt to access the #radius
private field in the Cylinder
class, you’ll get a SyntaxError
.
Weird syntax? Why not use private
keyword?
Class definitions were introduced in ES6 and the public opinion remained cool. ES2019 class fields require less code, aid readability, and enable some interesting object-oriented programming possibilities.
Using #
to denote private fields has received some criticism, primarily because it’s ugly and feels like a hack.
Most languages implement a private
keyword, so attempting to use that member outside the class will be rejected by the compiler. JavaScript is interpreted. Consider the following code:
NOTE: Vanilla Javascript does not support private
keyword but it won't hurt to assume for now that the private
keyword in classes is supported.
class MyCircle {
private rad = 15;
#radius
}
const myCircle = new MyCircle();
myCircle.rad = 20;
After instantiating our class(const myCircle = new MyCircle();
), we are trying to access the private rad
property(myCircle.rad = 20;
).This would have thrown a runtime error on the last line, but that’s too much consequence for simply attempting to set a private property.
As you may not know, JavaScript ES5 permitted property modification on any object. Javascript classes are objects under the hood. So throwing a runtime error for trying to set a private property of our class is really like setting your own rules/conventions up in flames🔥.
Although insipid to the eyes, the #
notation is invalid outside a class definition. Attempting to access myCircle.#radius
throws a syntax error.
The syntax error
is logical since in Javascript, property names may either start with an underscore or a letter.
Hit the like button and please consider following me on twitter to keep abreast with what am upto these days. Follow me here in dev.to to stay tuned when my next article comes up! Peace✌️
Top comments (2)
Thanks, very helpful explanation of the syntax! It did not make sense why "private" was working in TS but not in JS. Now I know, this was just what I was looking for!
Yes Javascript is such a wonderful language