Definição de Classes - JavaScript
Com a introdução do padrão ES2015 (ES6) no JavaScript, surgiu uma nova maneira de definir objetos: através de classes. Uma classe descreve o estado e o comportamento de um objeto, sendo o próprio objeto uma encarnação específica ou instância da classe. O sintaxe das classes serve como uma construção alternativa, semelhante às funções construtoras, permitindo definir um novo tipo de objeto.
É importante notar que, apesar do suporte a classes, o JavaScript não é uma linguagem de programação orientada a objetos clássica como Java ou C#. As classes em JavaScript são essencialmente o que se chama de "açúcar sintático" sobre as funções construtoras, oferecendo uma forma mais conveniente de criar objetos. Na realidade, no JavaScript, os objetos ainda são criados com base em objetos ou protótipos.
Para definir uma classe, usa-se a palavra-chave class
class Person {}
Após a palavra class
Person
Esta é a forma mais comum de definir uma classe, mas existem outros métodos. Por exemplo, também é possível definir uma classe anônima e atribuí-la a uma variável ou constante:
const Person = class {}
Ou mesmo criar uma classe não anônima e atribuí-la a uma variável ou constante:
const User = class Person {}
Criação de Objetos
Uma classe é uma representação geral de algumas entidades ou objetos. A encarnação concreta dessa representação, a classe, é o objeto. Após a definição da classe, podemos criar objetos da classe usando o construtor:
class Person {}
const tom = new Person();
const bob = new Person();
Para criar um objeto usando o construtor, primeiro usa-se a palavra-chave new
É importante observar que, diferentemente das funções, para usar uma classe, ela deve ser definida primeiro. Por exemplo, no código a seguir, ocorrerá um erro, pois tentamos usar a classe antes de sua definição:
const tom = new Person(); // Erro - Uncaught ReferenceError: Cannot access 'Person' before initialization
class Person {}
Se a definição da classe for atribuída a uma variável ou constante, podemos usar o nome dessa variável/constante para criar objetos da classe:
const User = class Person {}
const tom = new User();
console.log(tom);
No código acima, embora usemos a chamada new User()
Person
Campos e Propriedades da Classe
Campos e propriedades são usados para armazenar dados ou o estado de um objeto em uma classe.
Assim, class Person
Person
class Person {
name;
age;
}
const tom = new Person();
tom.name = "Tom";
tom.age = 37;
console.log(tom.name); // Tom
console.log(tom.age); // 37
A definição de um campo basicamente apresenta seu nome:
name;
age;
Aqui, o campo name
age
Após criar um objeto da classe, podemos acessar esses campos. Para isso, após o nome do objeto, o nome do campo é especificado com um ponto:
tom.name = "Tom"; // define o valor do campo
console.log(tom.name); // obtém o valor da propriedade
Nos exemplos acima, os campos da classe também podem ser chamados de propriedades. Na prática, propriedades representam campos acessíveis externamente ou públicos da classe. Mais adiante, discutiremos quando os campos são privados, ou seja, inacessíveis externamente. Mas por enquanto, é importante entender que propriedades e campos públicos são a mesma coisa. E nos exemplos acima, os campos name e age também podem ser chamados de propriedades.
Se necessário, podemos atribuir alguns valores iniciais aos campos:
class Person {
name = "Unknown";
age = 18;
}
const tom = new Person();
console.log(tom.name); // Unknown
tom.name = "Tom";
console.log(tom.name); // Tom
Comportamento da Classe e seus Métodos
Além de armazenar dados que definem o estado do objeto, uma classe pode ter métodos que definem o comportamento do objeto - ações que o objeto executa. Por exemplo, vamos definir alguns métodos na classe Person:
class Person {
name;
age;
move(place) {
console.log(`Go to ${place}`);
}
eat() {
console.log("Eat apples");
}
}
const tom = new Person();
tom.move("Hospital"); // Go to Hospital
tom.move("Cinema"); // Go to Cinema
tom.eat(); // Eat apples
Aqui, definimos o método move()
eat()
Referência a Campos e Métodos dentro da Classe: a Palavra this
E se quisermos nos referir aos campos da classe ou a outros métodos dela em seus métodos? Nesse caso, antes do nome do campo/propriedade ou método, é usada a palavra-chave this
Por exemplo, vamos definir um método que exibe informações sobre o objeto:
class Person {
name;
age;
print() {
console.log(`Name: ${this.name} Age: ${this.age}`);
}
}
const tom = new Person();
tom.name = "Tom";
tom.age = 37;
tom.print(); // Name: Tom Age: 37
const bob = new Person();
bob.name = "Bob";
bob.age = 41;
bob.print(); // Name: Bob Age: 41
Definição do Construtor
Para criar um objeto de uma classe, usa-se um construtor:
const bob = new Person();
A chamada do construtor padrão, que está presente nas classes, representa a chamada de um método que tem o mesmo nome da classe e retorna um objeto dessa classe.
Mas também podemos definir nossos próprios construtores nas classes:
class Person {
name;
age;
constructor() {
console.log("Chamada do construtor");
}
print() {
console.log(`Name: ${this.name} Age: ${this.age}`);
}
}
const tom = new Person(); // Chamada do construtor
const bob = new Person(); // Chamada do construtor
O construtor é definido usando um método chamado constructor
const tom = new Person();
veremos a mensagem correspondente no console do navegador.
Geralmente, o objetivo do construtor é inicializar o objeto com alguns dados iniciais:
class Person {
name;
age;
constructor(pName, pAge) {
this.name = pName;
this.age = pAge;
}
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("Bob", 41);
bob.print() // Name: Bob Age: 41
Aqui, o construtor recebe dois parâmetros e passa seus valores para os campos da classe. Assim, ao criar um objeto, podemos passar valores correspondentes para esses parâmetros ao construtor:
const tom = new Person("Tom", 37);
Vale notar que, no exemplo acima, a definição de campos da classe é redundante. Referenciar os campos no construtor através de this
class Person {
constructor(pName, pAge) {
this.name = pName;
this.age = pAge;
}
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("Bob", 41);
bob.print() // Name: Bob Age: 41
Expressões de Classe
O JavaScript também permite definir classes através de expressões de classe (class expression). A classe é atribuída a uma variável/constante, através da qual pode-se referenciar essa classe posteriormente:
const Person = class {
constructor(pName, pAge) {
this.name = pName;
this.age = pAge;
}
print() {
console.log(`Name: ${this.name} Age: ${this.age}`);
}
}
const tom = new Person("Tom", 38);
tom.print();
Obtenção do Protótipo
Assim como a função-construtora, a classe tem um protótipo que pode ser obtido por métodos padrão:
class Person {
constructor(pName, pAge) {
this.name = pName;
this.age = pAge;
}
print() {
console.log(`Name: ${this.name} Age: ${this.age}`);
}
}
const tom = new Person("Tom", 37);
// obtenção do protótipo
console.log(Person.prototype); // através da propriedade prototype da classe
console.log(tom.__proto__); // através da propriedade __proto__ do objeto
console.log(Object.getPrototypeOf(tom)); // através da função Object.getPrototypeOf e do objeto
console.log(tom.constructor); // obtenção da função-construtora (definição do tipo) do objeto