Campos e métodos privados em JavaScript
Nos tópicos anteriores, abordamos o uso de uma classe cujas propriedades e métodos eram acessíveis externamente, permitindo que fossem utilizados em qualquer parte do programa. Por exemplo:
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
Por um lado, é excelente podermos utilizar a funcionalidade da classe em nosso programa e acessar suas propriedades e métodos. Contudo, isso também pode ser uma fonte de problemas potenciais. Como visto no exemplo acima, podemos alterar o nome de uma pessoa. Mas e se quisermos impedir que o nome inicial possa ser alterado no programa? Além disso, podemos modificar a idade de uma pessoa para qualquer número, que pode representar uma idade incorreta, como um valor negativo.
Às vezes é necessário que os dados ou ações não possam ser acessados externamente, sendo acessíveis apenas dentro da própria classe. Em outras palavras, tornar as propriedades e métodos da classe privados — disponíveis somente para essa classe. E o JavaScript oferece as ferramentas necessárias para isso. Para tanto, os nomes dos campos e métodos devem começar com o símbolo #
.
Campos Privados
Os nomes dos campos privados são precedidos pelo símbolo #
:
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"; // ! Erro - não é possível acessar o campo privado
// tom.#age = -45; // ! Erro - não é possível acessar o campo privado
tom.print(); // Name: Tom Age: 37
No exemplo acima, os campos privados #name
e #age
são definidos. Estabelecer e obter seus valores só é possível dentro da classe Person
. Fora dela, eles não estão acessíveis, portanto, qualquer tentativa de acessá-los por meio do nome do objeto resultará em um erro. Se ainda precisarmos acessá-los de alguma forma, podemos definir métodos para isso. Por exemplo, o método print()
acima obtém seus valores e os exibe no console. Podemos também definir métodos para ajustar esses valores:
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
Neste caso, o método setAge
verifica a validade do valor passado e, se estiver correto, redefine a idade.
Métodos Privados
Os nomes dos métodos privados também são precedidos pelo símbolo #
:
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"); // ! Erro - não é possível acessar o método privado
No exemplo acima, o método privado #checkName
realiza uma verificação condicional do nome. Se ele não for "admin", retorna o valor fornecido. Também não podemos acessar esse método fora da classe.
Assim, campos e métodos privados são uma maneira de proteger os dados e ações de uma classe, tornando-os acessíveis apenas dentro dela. Isso ajuda a garantir que os dados sejam manipulados corretamente e que a lógica da classe seja segura.