JavaScript POO Intermediário
Protótipos
Em JavaScript, herança funciona através de protótipos: todo objeto tem uma referência interna a outro objeto, chamado de seu protótipo. Quando você acessa uma propriedade que não existe no objeto, o motor JS sobe pela cadeia de protótipos até encontrá-la ou chegar a null. Isso é diferente de linguagens baseadas em classes: aqui, objetos herdam diretamente de outros objetos.
A função Object.create(proto) cria um novo objeto cujo protótipo é proto, permitindo montar cadeias de herança de forma explícita. Já Object.getPrototypeOf(obj) lê o protótipo, enquanto obj.__proto__ é uma forma legada (e desencorajada) de acessá-lo. A propriedade prototype só existe em funções construtoras e é usada para definir o protótipo dos objetos criados com new.
Entender a diferença entre __proto__ (protótipo do objeto) e .prototype (protótipo dos futuros objetos criados por uma função) evita confusões comuns. Com Object.create, você pode implementar herança prototípica sem classes, controlando manualmente o encadeamento.
Pontos-chave
- A cadeia de protótipos é a busca de uma propriedade subindo de objeto em objeto até
null. Object.create(proto)cria um objeto cujo protótipo interno éproto.obj.__proto__eObject.getPrototypeOf(obj)acessam o protótipo do objeto;.prototypeé uma propriedade de funções.- Herança prototípica permite que objetos compartilhem métodos sem duplicá-los.
- Sobrescrever um método no objeto filho não altera o protótipo, apenas cria uma propriedade própria.
// Objeto base (protótipo)
const animal = {
falar() {
return `${this.nome} faz um som.`;
}
};
// Cria um objeto cujo protótipo é 'animal'
const cachorro = Object.create(animal);
cachorro.nome = 'Rex';
cachorro.falar = function() {
return `${this.nome} late.`;
};
// Cria outro objeto herdando de 'animal'
const gato = Object.create(animal);
gato.nome = 'Mimi';
console.log(cachorro.falar()); // Rex late. (método próprio)
console.log(gato.falar()); // Mimi faz um som. (herdado)
// Verificando a cadeia de protótipos
console.log(Object.getPrototypeOf(cachorro) === animal); // true
console.log(Object.getPrototypeOf(animal) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // null
// Usando função construtora e prototype
function Pessoa(nome) {
this.nome = nome;
}
Pessoa.prototype.apresentar = function() {
return `Olá, eu sou ${this.nome}`;
};
const joao = new Pessoa('João');
console.log(joao.apresentar()); // Olá, eu sou João
console.log(Object.getPrototypeOf(joao) === Pessoa.prototype); // true