Voltar ao blog
javascriptfrontendfundamentos

Prototype e herança: como o JavaScript compartilha comportamento

08 de abril de 2026 às 20:12 - Por Larissa Santos

Prototype e herança: como o JavaScript compartilha comportamento

JavaScript não tem herança clássica como Java ou C#. Tem algo diferente: um sistema de protótipos onde objetos herdam de outros objetos. Entender essa diferença muda como você lê e escreve orientação a objetos em JS, e explica comportamentos que parecem estranhos à primeira vista.

O que é prototype

Todo objeto em JavaScript tem uma propriedade interna chamada [[Prototype]]. Ela aponta para outro objeto, e é por meio dessa referência que o JavaScript busca propriedades e métodos que não existem diretamente no objeto.

js
const animal = {
  respirar() {
    console.log("respirando...");
  }
};

const cachorro = Object.create(animal);
cachorro.latir = function() {
  console.log("au!");
};

cachorro.latir();    // "au!" — próprio do cachorro
cachorro.respirar(); // "respirando..." — veio do prototype

cachorro não tem respirar. O JavaScript sobe pela cadeia de protótipos até encontrar em animal. Isso se chama prototype chain.

Se não encontrar em nenhum nível, retorna undefined. O topo da cadeia é sempre Object.prototype, e acima dele é null:

text
cachorro → animal → Object.prototype → null

É essa busca encadeada que permite compartilhar comportamento entre objetos sem copiar nada.

Constructor functions e o prototype

Antes do ES6, a forma padrão de criar objetos com comportamento compartilhado era via constructor functions:

js
function Pessoa(nome) {
  this.nome = nome;
}

Pessoa.prototype.saudar = function() {
  console.log(`Olá, sou ${this.nome}`);
};

const p1 = new Pessoa("Ana");
const p2 = new Pessoa("João");

p1.saudar(); // "Olá, sou Ana"
p2.saudar(); // "Olá, sou João"

saudar não está em cada instância. Está em Pessoa.prototype, compartilhado entre todas. Quando você usa new, o JavaScript faz quatro coisas em sequência: cria um objeto vazio, aponta o [[Prototype]] dele para Pessoa.prototype, executa a função com this apontando para esse objeto e retorna o objeto.

Classes (ES6)

As classes introduzidas no ES6 são uma sintaxe mais limpa em cima do mesmo mecanismo. Não é um sistema novo, é açúcar sintático sobre protótipos.

js
class Pessoa {
  constructor(nome) {
    this.nome = nome;
  }

  saudar() {
    console.log(`Olá, sou ${this.nome}`);
  }
}

Por baixo, saudar ainda vai para Pessoa.prototype. O mecanismo é idêntico ao das constructor functions. A diferença é legibilidade e algumas proteções extras, como não poder chamar a classe sem new.

Herança

Herança em JavaScript é prototípica: um objeto herda de outro objeto. O extends configura essa cadeia.

js
class Animal {
  constructor(nome) {
    this.nome = nome;
  }

  respirar() {
    console.log(`${this.nome} está respirando`);
  }
}

class Cachorro extends Animal {
  latir() {
    console.log(`${this.nome} está latindo`);
  }
}

const rex = new Cachorro("Rex");
rex.respirar(); // herdado de Animal
rex.latir();    // próprio de Cachorro

A cadeia de protótipos fica assim:

text
rex → Cachorro.prototype → Animal.prototype → Object.prototype → null

Quando você chama rex.respirar(), o JavaScript não encontra em rex, não encontra em Cachorro.prototype, encontra em Animal.prototype e executa.

super

Usado para acessar o constructor ou métodos da classe pai:

js
class Animal {
  constructor(nome) {
    this.nome = nome;
  }

  descrever() {
    return `Sou ${this.nome}`;
  }
}

class Cachorro extends Animal {
  constructor(nome, raca) {
    super(nome);
    this.raca = raca;
  }

  descrever() {
    return `${super.descrever()}, da raça ${this.raca}`;
  }
}

const rex = new Cachorro("Rex", "Labrador");
rex.descrever(); // "Sou Rex, da raça Labrador"

Sem o super() no constructor de uma classe filha, o JavaScript lança um ReferenceError. Ele precisa ser chamado antes de qualquer uso de this, porque é o super que cria o objeto e vincula o this.

Pontos que costumam confundir

prototype vs __proto__

São coisas diferentes com nomes parecidos, o que gera bastante confusão.

Pessoa.prototype é a propriedade da função construtora, o objeto onde os métodos compartilhados ficam. instancia.__proto__ é a referência interna do objeto criado, que aponta para Pessoa.prototype. Na prática, p1.__proto__ === Pessoa.prototype é true.

A forma oficial de acessar o prototype de um objeto é Object.getPrototypeOf(instancia). O __proto__ funciona nos browsers modernos, mas é considerado legado.

Herança não copia, referencia

Diferente de algumas linguagens, JavaScript não copia os métodos para cada instância. Todas as instâncias referenciam o mesmo objeto no prototype. Isso é eficiente em memória, mas significa que se você alterar Pessoa.prototype.saudar em runtime, todas as instâncias já existentes são afetadas imediatamente.

Propriedades no objeto vs no prototype

js
class Pessoa {
  constructor(nome) {
    this.nome = nome; // cada instância tem a sua cópia
  }

  saudar() {}        // compartilhado no prototype
}

Propriedades definidas no constructor com this ficam no próprio objeto. Métodos definidos no corpo da classe ficam no prototype. Essa distinção importa quando você inspeciona objetos no DevTools ou usa hasOwnProperty.

Conclusão

O sistema de protótipos é o que está por baixo de toda orientação a objetos em JavaScript, incluindo as classes do ES6. Quando você chama um método, o JavaScript percorre a cadeia de protótipos até encontrá-lo ou retornar undefined. Quando você usa extends, está configurando essa cadeia.

Entender isso explica por que instancia.__proto__ === Classe.prototype é true, por que métodos são compartilhados em memória entre instâncias e por que alterar o prototype em runtime afeta todos os objetos que o referenciam.

As classes não escondem os protótipos. Elas só tornam a sintaxe mais legível.

Referências

Feito com e Vue.js
2026 © Larissa Santos