Page cover

7.8.4 - Classes e Objetos

🧬 Herança em JavaScript — O Poder de Reaproveitar Código!

🧬 Herança em JavaScript — O Poder de Reaproveitar Código!

A herança permite que um objeto "pegue emprestado" propriedades e comportamentos de outro. Isso evita repetição de código e ajuda a organizar melhor nossos programas. Em JavaScript, temos um jeito especial de fazer isso: herança prototipada.

💡 "Herança" é quando um objeto ou classe "filha" ganha tudo o que a classe "pai" tem — como poderes sendo passados de geração em geração! 🧙‍♂️➡️🧙‍♀️


🧱 Herança Prototipada: Como funciona?

No JavaScript, objetos herdam de outros objetos por meio de protótipos. Essa é a famosa cadeia de protótipos (prototype chain).

Quando tentamos acessar uma propriedade/método, o JS:

  1. Procura no próprio objeto.

  2. Se não encontrar, sobe para o protótipo (__proto__).

  3. Continua subindo na cadeia até encontrar ou chegar no null.

const animal = {
  tipo: "Animal",
  fazerSom() {
    console.log("Som genérico...");
  }
};

const cachorro = Object.create(animal);
cachorro.fazerSom(); // Som genérico...

🧠 Object.create() cria um novo objeto que herda de outro.


🧪 Exemplo com função construtora

📌 Herdando com e sem parâmetros

🔁 Definindo o protótipo e a referência do construtor

📎 Sobrescrevendo um método

⚠️ Importante: Sempre que usar Object.create() para herdar, lembre de corrigir a referência constructor.


🧠 Observação importante: cuidado com o Object.create() e o constructor!

Quando usamos Object.create() para criar herança entre objetos ou funções construtoras, estamos dizendo que o novo objeto deve herdar o protótipo de outro.

👀 Mas tem um detalhe importante que MUITA gente esquece:

O constructor do novo protótipo continua apontando para o construtor original (pai) — não para o filho! ⚠️

Vamos ver isso na prática:

➡️ Isso acontece porque Object.create(Pessoa.prototype) cria um novo objeto cujo __proto__ é Pessoa.prototype. Então, o constructor é herdado de lá também.


🛠️ Como corrigir?

Basta redefinir manualmente o constructor da função filha:

Agora tudo fica certo:


📌 Por que isso é importante?

O constructor é usado por ferramentas, IDEs e o próprio JavaScript para entender qual função criou um objeto. Se essa referência estiver errada, pode causar:

  • Confusão na hora de debugar 🔍

  • Problemas em frameworks que usam constructor automaticamente 🔧

  • Dificuldade na manutenção e leitura do código 😵‍💫


✅ Resumo rápido

Situação
O que acontece
Como resolver

Usou Object.create()

constructor aponta para o pai ❌

Redefina manualmente com Filho.prototype.constructor = Filho


🧠 Observação: Entendendo Professor.prototype, Professor.constructor e Professor.prototype.constructor

Essas três estruturas aparecem MUITO quando estamos lidando com herança e protótipos em JavaScript. Vamos entender cada uma delas de forma clara, com comparações e exemplos simples:


🧱 Professor.prototype

É o protótipo dos objetos que serão criados quando usamos new Professor(). Tudo o que colocamos aqui será compartilhado entre as instâncias criadas com essa função.


🧾 Professor.constructor

Isso se refere ao construtor da função em si, ou seja, Function! Lembre-se: em JavaScript, funções também são objetos — e o construtor das funções é Function.


🧬 Professor.prototype.constructor

Aqui está o ponto chave! Essa propriedade indica qual função construiu aquele protótipo.

Por padrão, ela aponta para a função construtora correta. Mas quando usamos Object.create() para fazer herança, ela pode acabar apontando para a função errada!


🧪 Recapitulando com uma tabela:

Expressão
O que é?
Tipo/Retorno

Professor.prototype

Protótipo dos objetos Professor

Objeto

Professor.constructor

Quem criou a função Professor

Function

Professor.prototype.constructor

Quem criou o protótipo do Professor

Professor (ou incorretamente Pessoa)


⚠️ Atenção: Confundir constructor com prototype.constructor é um dos erros mais comuns entre quem está começando com herança em JS! 😅


✅ Dica prática

Sempre que fizer herança com Object.create(), verifique se prototype.constructor está apontando corretamente. Se não estiver, corrija manualmente:


🔍 Observação: O que retorna quando usamos apenas Professor.prototype?

Quando você acessa Professor.prototype diretamente no seu código, está consultando o objeto protótipo associado à função construtora Professor.

📦 Em outras palavras:

🟰 Retorna um objeto que servirá como base para todas as instâncias criadas com new Professor().


🧠 O que tem dentro desse objeto?

Por padrão, ele começa assim:

Ou seja, ele contém:

  • A propriedade constructor, que aponta de volta para a própria função Professor.


💡 Pra que serve esse objeto?

É nesse Professor.prototype que você pode adicionar métodos ou propriedades compartilhadas entre todas as instâncias da função.

✅ Ambos os objetos compartilham o mesmo método sem duplicar o código na memória!


📌 Por que isso é importante?

Entender o que Professor.prototype retorna é essencial para:

  • Trabalhar com herança corretamente

  • Criar métodos otimizados

  • Entender como funciona o encadeamento de protótipos

  • Evitar confusão com __proto__ e prototype.constructor


🛑 Atenção

Professor.prototype não é o protótipo da função Professor. Ele é o protótipo que será usado pelas instâncias criadas com new Professor()!

🔁 Já o Professor.__proto__ (com dois underlines) aponta para Function.prototype, pois Professor é uma função.


✅ Resumo rápido

Expressão
Significado

Professor.prototype

Objeto usado como protótipo pelas instâncias criadas

new Professor().__proto__

Sempre é igual a Professor.prototype


📘 ECMAScript 2015 (ES6): Herança com classes

A sintaxe moderna com class facilita muito o uso da herança:


🔍 Como funciona por debaixo dos panos?

Mesmo com a sintaxe class, o JavaScript continua usando protótipos! A classe nada mais é que um açúcar sintático para facilitar a vida de quem programa.


🧩 Onde posso definir propriedades e métodos?

Local
Como declarar
Quando usar

Dentro da função construtora

this.nome = "..."

Quando cada instância precisa de um valor diferente

No próprio construtor (estático)

MinhaClasse.algumaFuncao = function () {}

Quando o método é da classe, não do objeto

No protótipo

MinhaClasse.prototype.metodo = function () {}

Quando todas as instâncias compartilham o mesmo comportamento


🧭 Quando usar herança em JavaScript?

✔️ Use quando:

  • Vários objetos compartilham lógica comum.

  • Você quer reaproveitar métodos entre objetos semelhantes.

  • Precisa organizar melhor responsabilidades e comportamentos.

🚫 Evite quando:

  • Os objetos têm pouco em comum.

  • A herança deixa o código mais confuso do que ajuda.

  • Composição seria mais clara do que herança.

💬 Dica: Uma boa regra é "preferir composição à herança", mas usar herança quando o comportamento for realmente compartilhado e hierárquico!


✅ Resumo prático

Conceito
Exemplo
Significado

call()

Pai.call(this)

Chama o construtor pai no contexto do filho

Object.create()

Filho.prototype = Object.create(Pai.prototype)

Faz herança prototipada

constructor

Filho.prototype.constructor = Filho

Corrige a referência do construtor

extends

class Filho extends Pai {}

Herança com classes (ES6)

super()

super()

Chama o construtor da superclasse

get/set

get nome() {}

Criam propriedades especiais

prototype

Classe.prototype.metodo = ...

Define métodos herdáveis


📚 Herança é uma ferramenta poderosa, mas deve ser usada com cuidado e propósito. Aprender como o JavaScript lida com isso te transforma num programador ou programadora muito mais preparado(a)! 🚀

Atualizado