JavaScript Private fields and methods

In previous topics, we used a class whose properties and methods were accessible from the outside, and accordingly we could refer to them anywhere in the program. For example:

class Person{
 
    constructor(name, age){
        this.name = name;
        this.age = age;
    }
    print(){
        console.log(`Name: ${this.name}  Age: ${this.age}`);
    }
}
const tom = new Person("Tom", 37);
tom.name = "Sam";
tom.age = -45;
tom.print();    // Name: Sam  Age: -45

On the one hand, it’s great that we can use the functionality of a class in our program, access its properties and methods. But this can be a source of potential problems. As seen in the example above, we can change the person’s name. But what if we don’t want the program to be able to change the initial name? We can also change the person’s age, but change it to any number that might represent an incorrect age (for example, negative).

Sometimes it is necessary that data or actions from outside the class cannot be accessed, and that they can only be accessed within the same class. Or in other words, make the properties and methods of the class private – available only for this class. And the JavaScript language provides the necessary tools for this. To do this, the names of fields and methods must begin with the pound sign # .

Private fields

The names of private fields are preceded by the # symbol :

class Person{
    #name;
    #age;
    constructor(name, age){
        this.#name = name;
        this.#age = age;
    }
    print(){
        console.log(`Name: ${this.#name}  Age: ${this.#age}`);
    }
}
const tom = new Person("Tom", 37);
// tom.#name = "Sam";   // ! Error - can't access private field
// tom.#age = -45;      // ! Error - can't access private field
tom.print();    // Name: Tom  Age: 37

The example above defines private fields #name and #age. You can only set and get their value inside the Person class. Outside of it they are not available. Therefore, when trying to access them through the object name, we will get an error:

tom.#name = "Sam";  // ! Error - can't access private field
tom.#age = -45;     // ! Error - can't access private field

If you need to somehow access them, then we can define methods for this. For example, the method above print()gets their values ​​and prints them to the console. Similarly, you can define methods for setting a value:

class Person{
    #name;
    #age= 1;
    constructor(name, age){
        this.#name = name;
        this.setAge(age);
    }
    setAge(age){
        if (age > 0 && age < 110) this.#age = age;
    }
    print(){
        console.log(`Name: ${this.#name}  Age: ${this.#age}`);
    }
}
const tom = new Person("Tom", 37);
tom.print();    // Name: Tom  Age: 37
tom.setAge(22);
tom.print();    // Name: Tom  Age: 22
tom.setAge(-1234);
tom.print();    // Name: Tom  Age: 22

In this case, the method setAge checks the correctness of the passed value, and if it is correct, resets the age. Private Methods The names of private methods are also preceded by the # symbol :

 
class Person{
    #name = "undefined";
    #age = 1;
    constructor(name, age){
        this.#name = this.#checkName(name);
        this.setAge(age);
    }
    #checkName(name){
        if(name!=="admin") return name;
    }
    setAge(age){
        if (age > 0 && age < 110) this.#age = age;
    }
    print(){
        console.log(`Name: ${this.#name}  Age: ${this.#age}`);
    }
}
const tom = new Person("Tom", 37);
tom.print();    // Name: Tom  Age: 37
const bob = new Person("admin", 41);
bob.print();    // Name: Undefined  Age 41
//let personName = bob.#checkName("admin"); // ! Error - can't access private method

In the example above, a private method is defined #checkName() that performs a conditional check on the name – if it is not equal to “admin”, then it returns the passed value. (For example, we don’t want the username to be “admin”). And also outside the class, we cannot access this method:

let personName = bob.#checkName("admin");   // ! Error

As a rule, such private methods are used to perform some auxiliary actions, such as the validation in the example above, which makes no sense to make available from outside.