Entendendo o Prototype

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