Uma das formas de criar objetos em JavaScript é usando a função construtora (constructor). Mas há um problema em criar objetos com o Constructor, pois ao executar uma função construtora, criando-se objetos, a engine JavaScript cria duas cópias da função construtora, ou seja, todo objeto criado utilizando a função Constructor terá a sua própria cópia de propriedades e métodos. Ou seja, torna-se redundante, pois não há sentido em ter duas instâncias de uma função fazendo a mesma coisa. Por exemplo:
function Humanos(nome, sobrenome){
this.nome = nome;
this.sobrenome = sobrenome;
this.nomeCompleto = function(){
return this.nome + " " + this.sobrenome;
}
}
let pessoa1 = new Humanos("João", "Silva");
let pessoa2 = new Humanos("José", "Silveira");
console.log(pessoa1);
console.log(pessoa2);
Utilizando o console.log, verificamos a criação de duas funções nomeCompleto(), e isso resulta em desperdício de memória.
E como resolver isso?
Ao criar uma função, o mecanismo JavaScript adiciona um protótipo (prototype) à função. Essa propriedade é um objeto denominado protótipo de objeto e possui um constructor por padrão. Esse constructor aponta de volta para a função na qual o prototype é uma propriedade. Podemos acessar a propriedade prototype da função usando nomeFuncao.prototype.
No nosso exemplo, a função Humanos possui uma propriedade prototype que aponta para o objeto prototype. O objeto prototype tem uma propriedade constructor e aponta de volta para a função Humanos. Confuso? Vamos verificar isso na nossa imagem:
Para acessar nossa propriedade prototype da função Humanos:
console.log(Humanos.prototype);
E isso nos mostrará que a função possui um objeto prototype com dua propriedades:
- constructor: aponta para a própria função Humanos;
- __proto__: propriedade utilizada no conceito de herança.
O Objeto pessoa1 criado usando a função construtora Humanos possui um __proto__ que aponta para o protótipo de objeto da função constructor.
Podemos verificar que o protótipo pessoa1.__proto__ e a propriedade Humanos.prototype são iguais:
Humanos.prototype === pessoa1.__proto__;
//true
Criaremos agora um novo objeto, chamado pessoa 2:
let pessoa2 = new Humanos("José", "Silveira");
Verificaremos que o protótipo pessoa2.__proto__ também é igual a propriedade Humanos.prototype:
Humanos.prototype === pessoa2.__proto__;
//true
E verificamos que a propriedade __proto__ dos dois objetos pessoas são estritamente iguais! Veja só:
pessoa1 === pessoa2;
//false
pessoa1.__proto__ === pessoa2.__proto__;
//true
E isso prova que as propriedades __proto__ de pessoa1 e pessoa2 apontam para o Humanos.prototype que criamos anteriormente!
Como o prototype é um objeto, podemos anexar propriedades e métodos ao objeto protótipo. Assim, permite que os objetos criados usando a função construtora compartilhem essas propriedades e métodos:
Humanos.prototype.nome = "Maria";
console.log(Humanos.prototype.nome);
Humanos.prototype["idade"] = 30;
console.log(Humanos.prototype["idade"]);
console.log(Humanos.prototype);
Você pode ver que as propriedades nome e idade foram adicionadas ao Humanos.prototype!
Quando tentamos acessar uma propriedade de um objeto, o JavaScript primeiro tenta encontrar a propriedade no objeto e, se a propriedade estiver presente no objeto, ele gera o seu valor. Se não estiver, ele tentará encontrar a propriedade no objeto prototype. Se for encontrada, o valor será retornado.
Exemplo:
Primeiro, criaremos uma função construtora vazia:
function Pessoa(){
}
Depois, adicionaremos as propriedades nome, idade e digaOla ao prototype da função Pessoa:
Pessoa.prototype.nome = "Maria";
Pessoa.prototype.idade = 30;
Pessoa.prototype.digaOla = function(){
console.log(this.nome + " diz Olá para você!");
};
Criaremos um objeto usando a função construtora Pessoa e acessaremos a propriedade nome usando o objeto criado:
let pessoa1 = new Pessoa();
console.log(pessoa1.nome);
E a saída será?
Maria
Gostou deste artigo? Comente abaixo!
Referência: https://medium.com/better-programming/prototypes-in-javascript-5bba2990e04b