Médio JavaScript

Cadeia de protótipos com função construtora

Enunciado

Crie uma função construtora Animal que recebe nome e define this.nome. No Animal.prototype, adicione o método falar() que retorna "<nome> faz um som". Crie uma função construtora Cachorro que herda de Animal usando Object.create(Animal.prototype), e no Cachorro.prototype sobrescreva falar() para retornar "<nome> late". Crie uma instância rex = new Cachorro('Rex') e imprima rex.falar() e rex instanceof Animal.

Requisitos

  • Usar função construtora Animal com propriedade nome.
  • Animal.prototype.falar deve retornar '<nome> faz um som'.
  • Cachorro deve herdar de Animal via Object.create(Animal.prototype).
  • Cachorro.prototype.falar deve retornar '<nome> late'.
  • Imprimir rex.falar() e rex instanceof Animal.

Código inicial

function Animal(nome) {
  // complete
}

// Adicione falar ao prototype

function Cachorro(nome) {
  // complete
}

// Configure herança e sobrescreva falar

// Crie rex e imprima

Saída esperada

Rex late
true
Ver dica

Dentro do construtor Cachorro, chame Animal.call(this, nome) para inicializar this.nome. Depois, Cachorro.prototype = Object.create(Animal.prototype) e redefina Cachorro.prototype.constructor = Cachorro.

Mostrar solução
function Animal(nome) {
  this.nome = nome;
}

Animal.prototype.falar = function() {
  return `${this.nome} faz um som`;
};

function Cachorro(nome) {
  Animal.call(this, nome); // chama o construtor pai
}

// Herda de Animal
Cachorro.prototype = Object.create(Animal.prototype);
Cachorro.prototype.constructor = Cachorro;

// Sobrescreve falar
Cachorro.prototype.falar = function() {
  return `${this.nome} late`;
};

const rex = new Cachorro('Rex');
console.log(rex.falar());
console.log(rex instanceof Animal);

Passo a passo

  1. Animal é uma função construtora que inicializa this.nome.
  2. Animal.prototype.falar define o método compartilhado.
  3. Cachorro chama Animal.call(this, nome) para reutilizar a inicialização.
  4. Cachorro.prototype = Object.create(Animal.prototype) cria a cadeia de protótipos.
  5. Redefinimos Cachorro.prototype.constructor para não perder a referência.
  6. Sobrescrevemos falar no protótipo de Cachorro.
  7. rex é criado com new Cachorro('Rex') e herda de Cachorro.prototype, que herda de Animal.prototype.
  8. rex.falar() usa o método sobrescrito; rex instanceof Animal verifica a cadeia.

Por que funciona

A herança prototípica é montada manualmente: Cachorro.prototype tem como protótipo Animal.prototype. Assim, rex acessa falar em Cachorro.prototype e, se não existisse, subiria para Animal.prototype. O instanceof percorre a cadeia e encontra Animal.prototype.

Erros comuns

  • Esquecer Animal.call(this, nome) — this.nome fica undefined.
  • Fazer Cachorro.prototype = Animal.prototype — ambos compartilham o mesmo protótipo; sobrescrever falar afeta Animal também.
  • Não redefinir constructor — rex.constructor apontaria para Animal.

Outra forma de resolver

Com classes ES6:

class Animal {
  constructor(nome) { this.nome = nome; }
  falar() { return `${this.nome} faz um som`; }
}
class Cachorro extends Animal {
  falar() { return `${this.nome} late`; }
}

É mais legível, mas internamente usa a mesma cadeia de protótipos.

Saída esperada

Rex late
true