Javascript — Prototypes e Herança
Prototype Chain
Chamada de cadeia de protótipos, é a forma de herança entre objetos, ou seja, como um objeto pode acessar métodos e propriedades de outro (geralmente seu construtor)
Neste exemplo abaixo, o meuArray só possui as propriedades 1, 2, 3, 4 porém ele herda todas as propriedades e métodos do seu construtor Array (ex: map, lentgh etc) que por sua vez também herda do seu construtor Object. Então de acordo a cadeia de prototipos, primeiro a engine busca o métodos/propriedade requisitado no meuArray, mas caso não encontre ele vai buscar nos protótipos, nível após nível.
const meuArray = [1, 2, 3, 4];
// meuArray.__proto__ -> Array.__proto -> Object.__proto__ -> nullconst novoArray = meuArray.map(numero => numero + 2);
// [3, 4, 5, 6]
Observe que o método map não estava originalmente presente no meuArray, porém estava contigo dentro do __proto__ herdado do seu construtor Array
Prototype
São os métodos e propriedades que serão herdados na cadeia
Por exemplo uma função construtora Pessoa tem um método alterarNome adicionado ao seu objeto prototype. Esse método será herdado por todos os objetos criados a partir dela, conforme demonstrado abaixo, mas lembrando que esse método não estará presente no objeto recém criado:
function Pessoa(nome, idade) {
this.nome = nome;
this.idade = idade;
}Pessoa.prototype.alterarNome = function(nome) {
this.nome = nome;
}const lucas = new Pessoa('lucas', 25);
lucas.nome // 'lucas'lucas.alterarNome('lucas batista');
// método alterarNome foi herdado do construtor Pessoa
lucas.nome // 'lucas batista'
__proto__
São os métodos e propriedades herdados na cadeia (não devem ser manipulados).
É nele que é buscado quando um método ou propriedade é solicitada e não está presente no nível atual, a engine vai buscar se existe esse método herdado.
function Pessoa(nome, idade) {
this.nome = nome;
this.idade = idade;
}Pessoa.prototype.alterarNome = function(nome) {
this.nome = nome;
}const lucas = new Pessoa('lucas', 25);
lucas.nome // 'lucas'lucas.alterarNome('lucas batista');
lucas.nome; // 'lucas batista'lucas.__proto__;
// {
// alterarNome(){
// this.nome = nome;
// }
// }