In the topic of object-oriented programming, the properties and methods can be divided into two categories, private and public.
The public properties are those that can be accessed from outside of the object. All of the examples we've seen so far are public properties.
Private properties cannot be accessed from the outside and can only be used by methods in the same class.
Most other programming languages offer a language-level way to define private properties, usually with the keyword private
. But this feature has been missing in JavaScript for a long time.
Private properties
So JavaScript developers decided on a convention, that is, if a property name starts with an underscore (_
), that property is considered private and should not be accessed from the outside.
1class User {
2 constructor(name) {
3 this._name = name; // This property is private
4 this.status = "Admin"; // This property is public
5 }
6}
Technically, this _name
property can still be accessed.
1let user = new User("John Doe");
2
3console.log(user._name);
1John Doe
But you shouldn't do that in your codebase to avoid security risks. Instead, create a name
setter to manipulate the _name
property.
1class User {
2 constructor() {
3 this._name;
4 }
5
6 set name(name) {
7 this._name = name;
8 }
9}
10
11let user = new User();
12
13user.name = "John Doe";
14
15console.log(user);
1User { _name: 'John Doe' }
The reason that this is safer is that you can add a verification mechanism in the setter.
1class User {
2 constructor() {
3 this._name;
4 }
5
6 set name(name) {
7 if (name.length > 5 && name.length < 15) {
8 this._name = name;
9 } else {
10 this._name = "John Doe";
11 }
12 }
13}
14
15let user = new User();
16
17user.name = "Alice Cooper";
18console.log(user);
19
20user.name = "qwertyuiopasdfghjklzxcvbnm";
21console.log(user);
1User { _name: 'Alice Cooper' }
2User { _name: 'John Doe' }
This makes sure that the data is verified before the actual _name
property is altered. In this case, only strings longer than five characters and shorter than 15 characters will be accepted. If the input is invalid, "John Doe"
will be set as the _name
.
If you want to retrieve the _name
property, use a name
getter instead of using user._name
.
1class User {
2 constructor() {
3 this._name;
4 }
5
6 get name() {
7 return this._name;
8 }
9
10 set name(name) {
11 if (name.length > 5 && name.length < 15) {
12 this._name = name;
13 } else {
14 this._name = "John Doe";
15 }
16 }
17}
18
19let user = new User();
20
21user.name = "Alice Cooper";
22
23console.log(user.name);
1Alice Cooper
Private methods
Methods can also be private, which are often helper functions for other methods. They are defined in a similar way.
1class User {
2 constructor() {
3 this._name;
4 }
5
6 _private() {
7 console.log("This method shouldn't be accessed from the outside.");
8 }
9}
Again, the underscore syntax is only a convention that JavaScript developers have agreed upon. It is not supported on a language level. They can still be accessed from the outside, but you shouldn't.
Language level support is coming
The language-level support for private properties and methods might be coming to JavaScript very soon. It is specified in a proposal, but not yet included in the official standard.
Instead of an underscore, this syntax uses a #
. And instead of defining properties in the constructor()
, private properties are defined at the same level as the methods.
1class User {
2 constructor() {
3 this.status = "Admin";
4 }
5
6 #name; // This is a private property
7
8 get name() {
9 return this.#name; // The private property can only be accessed from the inside with "this".
10 }
11
12 set name(name) {
13 if (name.length > 5 && name.length < 15) {
14 this.#name = name;
15 } else {
16 this.#name = "John Doe";
17 }
18 }
19
20 #private() {
21 console.log("This method couldn't be accessed from the outside.");
22 }
23
24 public() {
25 this.#private();
26 console.log("But can be accessed by another method in the same class.");
27 }
28}
29
30let user = new User();
31
32user.name = "Alice Cooper";
33
34console.log(user.name); // -> Alice Cooper
35user.public();
1Alice Cooper
2This method couldn't be accessed from the outside.
3But can be accessed by another method in the same class.