<h2>Object.create: A Base da Herança Real</h2>
<p><code>Object.create()</code> é o método fundamental para criar herança real em JavaScript. Diferente de construtores tradicionais, ele permite criar um objeto com um protótipo específico, oferecendo controle total sobre a cadeia de protótipos. Esse método foi introduzido no ES5 e revolucionou como implementamos herança, sendo a base das práticas modernas.</p>
<pre><code class="language-javascript">const animal = {
fazer_som: function() {
return "Som genérico";
},
dormir: function() {
return "Zzzzz...";
}
};
const cachorro = Object.create(animal);
cachorro.fazer_som = function() {
return "Au au!";
};
cachorro.buscar = function() {
return "Trazendo a bolinha!";
};
console.log(cachorro.fazer_som()); // "Au au!"
console.log(cachorro.dormir()); // "Zzzzz..." (herdado)
console.log(cachorro.buscar()); // "Trazendo a bolinha!"</code></pre>
<p>Note como <code>cachorro</code> herda <code>dormir()</code> sem tê-lo definido. A busca passa pela cadeia até encontrar em <code>animal</code>. <code>Object.create()</code> também aceita um segundo argumento com descritores de propriedade, permitindo configuração granular:</p>
<pre><code class="language-javascript">const veiculo = {
acelerar: function() { return "Acelerando..."; }
};
const carro = Object.create(veiculo, {
portas: {
value: 4,
writable: true,
enumerable: true
},
marca: {
value: "Toyota",
writable: false,
enumerable: true
}
});
console.log(carro.portas); // 4
console.log(carro.marca); // "Toyota"
carro.portas = 2; // Permitido
// carro.marca = "Honda"; // Erro em strict mode</code></pre>
<h2>Object.getPrototypeOf: Inspecionando a Cadeia</h2>
<p><code>Object.getPrototypeOf()</code> retorna o protótipo de um objeto, permitindo navegar e inspecionar a cadeia de protótipos. É essencial para debugging e para construir sistemas que dependem de metaprogramação. Ao contrário de <code>__proto__</code>, é a forma padronizada e recomendada.</p>
<pre><code class="language-javascript">const pessoa = {
saudar: function() { return "Olá!"; }
};
const joao = Object.create(pessoa);
joao.nome = "João";
const prototipo_joao = Object.getPrototypeOf(joao);
console.log(prototipo_joao === pessoa); // true
console.log(prototipo_joao.saudar()); // "Olá!"
// Navegar a cadeia completa
function mapear_cadeia(obj) {
let atual = obj;
let profundidade = 0;
while (atual !== null) {
console.log(Nível ${profundidade}:, Object.keys(atual));
atual = Object.getPrototypeOf(atual);
profundidade++;
}
}
mapear_cadeia(joao);
// Nível 0: [ 'nome' ]
// Nível 1: [ 'saudar' ]
// Nível 2: []</code></pre>
<p>Combine <code>getPrototypeOf()</code> com <code>Object.setPrototypeOf()</code> para modificar a cadeia dinamicamente, embora com cuidado devido ao impacto em performance:</p>
<pre><code class="language-javascript">const funcionario = {
trabalhar: function() { return "Trabalhando..."; }
};
const gerente = {
liderar: function() { return "Liderando time..."; }
};
let carlos = Object.create(funcionario);
console.log(carlos.trabalhar()); // "Trabalhando..."
// Mudar protótipo dinamicamente
Object.setPrototypeOf(carlos, gerente);
console.log(carlos.liderar()); // "Liderando time..."
// carlos.trabalhar(); // Erro: não está mais na cadeia</code></pre>
<h2>Herança Real com Múltiplos Níveis</h2>
<p>A verdadeira potência emerge ao criar hierarquias complexas que refletem relacionamentos reais do domínio. Diferente de herança de classe (que é sintetizada), aqui a herança é literal: objetos herdam diretamente de outros objetos.</p>
<pre><code class="language-javascript">const ser_vivo = {
respirar: function() { return "Respirando..."; },
reproduzir: function() { return "Reproduzindo..."; }
};
const animal_avancado = Object.create(ser_vivo);
animal_avancado.mover = function() { return "Movendo..."; };
animal_avancado.comer = function() { return "Comendo..."; };
const mamifero = Object.create(animal_avancado);
mamifero.amamentar = function() { return "Amamentando..."; };
const cao = Object.create(mamifero);
cao.latir = function() { return "Au au!"; };
cao.nome = "Rex";
// Verificar a cadeia
console.log(cao.latir()); // "Au au!"
console.log(cao.amamentar()); // "Amamentando..."
console.log(cao.comer()); // "Comendo..."
console.log(cao.respirar()); // "Respirando..."
// Verificar onde cada método vive
console.log(Object.getPrototypeOf(cao) === mamifero); // true
console.log(Object.getPrototypeOf(mamifero) === animal_avancado); // true
console.log(Object.getPrototypeOf(animal_avancado) === ser_vivo); // true</code></pre>
<h3>Padrão OLOO (Objects Linking to Objects)</h3>
<p>Este padrão, popularizado por Kyle Simpson, evita construtor functions totalmente:</p>
<pre><code class="language-javascript">const controle_animal = {
init: function(nome, energia) {
this.nome = nome;
this.energia = energia;
return this;
},
gastar_energia: function(qtd) {
this.energia -= qtd;
return this.energia > 0 ? ${this.nome} tem ${this.energia}% de energia : "Sem energia!";
}
};
const controle_passaro = Object.create(controle_animal);
controle_passaro.voar = function(km) {
return this.gastar_energia(km * 2) + " - Voando!";
};
const passaro = Object.create(controle_passaro).init("Tweety", 100);
console.log(passaro.voar(10)); // "Tweety tem 80% de energia - Voando!"
console.log(passaro.gastar_energia(20)); // "Tweety tem 60% de energia"</code></pre>
<h2>Conclusão</h2>
<p>Dominar <code>Object.create()</code> e <code>Object.getPrototypeOf()</code> revela que a verdadeira herança em JavaScript não precisa de classes ou construtores complexos. <strong>Primeiro aprendizado:</strong> herança real é objetos ligados a objetos; a cadeia de protótipos é uma busca linear por propriedades. <strong>Segundo aprendizado:</strong> <code>Object.create()</code> oferece controle fino, desde descritores até criação de hierarquias limpas, enquanto <code>getPrototypeOf()</code> permite inspecionar e modificar essa relação. <strong>Terceiro aprendizado:</strong> padrões como OLOO demonstram que código mais legível e flexível emerge quando abandonamos a mentalidade de classes e abraçamos a composição de objetos.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/create" target="_blank" rel="noopener noreferrer">MDN Web Docs - Object.create()</a></li>
<li><a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf" target="_blank" rel="noopener noreferrer">MDN Web Docs - Object.getPrototypeOf()</a></li>
<li><a href="https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed/objects-classes" target="_blank" rel="noopener noreferrer">You Don't Know JS: this & Object Prototypes - Kyle Simpson</a></li>
<li><a href="https://javascript.info/prototype-inheritance" target="_blank" rel="noopener noreferrer">JavaScript.info - Prototypal Inheritance</a></li>
<li><a href="https://www.ecma-international.org/ecma-262/" target="_blank" rel="noopener noreferrer">ECMAScript 2015 Specification - Prototype Objects</a></li>
</ul>