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, segue-se o nome da classe (neste caso, a classe é chamada Person), e então o corpo da classe é definido entre chaves.

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. Em seguida, o construtor é chamado, que é essencialmente uma chamada de função pelo nome da classe. Por padrão, as classes têm um construtor sem parâmetros. Portanto, neste caso, ao chamar o construtor, nenhum argumento é passado.

É 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(), o objeto criado representa a classe 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 foi definida anteriormente, representando uma pessoa. Uma pessoa tem características distintas, como nome e idade. Vamos definir campos na classe Person para armazenar esses dados:

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 é definido para armazenar o nome da pessoa, e o campo age para armazenar a idade da pessoa.

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(), que representa o movimento condicional de uma pessoa. Como parâmetro, o método recebe o lugar para onde a pessoa vai. O segundo método, eat(), representa o processo condicional de alimentação.

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, que neste caso indica o objeto atual.

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. Essencialmente, é um método comum que pode receber parâmetros. Neste caso, o construtor simplesmente exibe uma mensagem no console. Assim, ao executar a linha

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 é efetivamente equivalente à sua definição, e neste caso, podemos remover a definição dos campos:

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
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com