0

Herança com Prototype em JavaScript

Samuel Costa
Samuel Costa

Se você é novo ou não em desenvolvimento web, deve ter aprendido que javascript e orientação a objetos adam de mãos dadas. 


Qualquer artigo, referência que você ler vai trazer as duas referências, e isso é o que torna javascript tão especial.


Meu artigo fala sobre prototype, e saber sobre objetos vai ser primordial para você entender. Digo por experiência própria,


entender protótipos é como peitar a feiticeira escarlate pra pegar a joia da mente, mas depois que você coloca essa joia na sua


manopla de conhecimentos, você melhora suas habilidades com um estalo (mas pelamor multiplique os recursos e não mate meio mundo blz?)


Vamos lá


Quando criamos objetos, geralmente usamos essa forma:


var obj = {}; // chamada implícita para criacao de objetos 


simples e elegante, mas para o interpretador, é a mesma coisa que:


var obj = new Object(); chamada explicita para criacao de objetos


Perceba que é como se você criasse uma instancia de objetos, herdando atributos e métodos.


__proto__ e prototype


Abra o navegador e depois vá para o console. Coloque essa função:


  function soma (a, b) => return a + b


depois: 


console.log(soma.prototype) 


Veja que a função possui um construtor (o que ela precisa para funcionar) e um objeto __proto__. 


O prototype é o modelo para criar instancias da sua função. Toda vez que você chama 


soma(1,3), é o prototype que atua como construtor.


Já o __proto__ é a referencia a outro objeto que tem outras propriedades. Note, referência e não instancia. Ele é apenas o endereço


de memória onde o objeto está armazenado. Por isso que as documentações oficiais dizem claramente: NÃO ALTERE AS PROPRIEDADES E MÉTODOS __proto__


isso seria catastrófico.


Assim, o __proto__ de uma função é igual ao prototype de Function, assim como __proto__ de um objeto literal é igual a Object.prototype


Para entender como isso é útil, vamos antes ver um conceito chamado cadeia de protótipos, acredito q isso vai te ajudar a entender melhor:


Quando você cria um objeto e procura alguma propriedade nele, a engine do js procura a propriedade no seu objeto:


let carro = {
  nome:"gol",
  motor:1.6
}


// quero o motor: esta no objeto carro


Se ele não encontra no objeto, ele vai procurar no __proto__, que lembrando, é o mesmo q Object.prototype. Ele vai procurar se existe


alguma referencia daquela propriedade ou método. 


let carro = {
  nome:"gol",
  motor:1.6
} 


// quero o preço: não existe no objeto, logo vou procurar no __proto__ deste objeto, que é Object.prototype.


por fim, ele procura no __proto__ de Object.prototype que é o estágio final da cadeia. Como ele não herda de lugar nenhum, seu resultado é null.


Com isso em mente, vamos trabalhar com o prototype de nossos objetos (não com o __proto__). Se ainda não ficou claro, teste o seguinte:


Cadeia prototype
biz.__proto__ === Moto.prototype // true
biz.__proto__.__proto__ === Object.prototype // true
biz.__proto__.__proto__.__proto__ === null // true


Vamos criar uma função e associar um método a ela:



function Moto(){
  Moto.prototype.acelerar = () => console.log('raannnPá')
}

let cg = new Moto()
cg.acelerar()


Perceba q o método acelerar está anotado no prototype de Moto, e o objeto cg possui esse método por herança:


cg.__proto__
{acelerar: ƒ, constructor: ƒ}
Moto.prototype
{acelerar: ƒ, constructor: ƒ}


Logo, por herança temos a referência da memória deste método e não uma nova instancia desse método. 

function Moto(){
  this.acelerar = () => console.log('raannnPá')
}

cg.acelerar() // criada nova instancia, novo endereco e espaco em memória.


Isso é bom principalmente para a performance da nossa aplicação. Imagine que temos 5000 motos Cg acelerando ao mesmo tempo.


No primeiro exemplo teríamos 1 método acelerar para as 5000 instancias sendo passado por referencia. No segundo seriam 5000 métodos, cada 


um para cada instância.

Comparativo:


function Moto(){
  this.acelerar = () => console.log('raannnPá')
}

let motos = [];

console.time('usando objetos locais: acelerar')

for(let i = 0; i < 200000; i++){
  motos.push(new Moto())
}

console.timeEnd('usando objetos locais: acelerar')

>>>usando objetos locais: acelerar: 77.781ms


com prototype.acelerar:


function Moto(){
  Moto.prototype.acelerar = () => console.log('raannnPá')
}

let motos = [];

console.time('usando prototype')

for(let i = 0; i < 200000; i++){
  motos.push(new Moto())
}

console.timeEnd('usando prototype')

usando prototype: 56.14ms


quase 30% a menos de tempo com um método que apenas coloca texto na tela. Imagine a diferença para um sistema com milhares de classes, com vários


métodos realizando as mais diversas operações.


Esse foi apenas um artigo para dar uma luz no assunto; o conceito é muito abrangente pode ser usado em outras aplicações.


Espero que tenha gostado do artigo. Se encontrou algum erro ou gostaria de fazer uma crítica construtiva, sinta-se a vontade para tal.


Deixarei alguns artigos que me ajudaram a construir este, e fica minha dica: Se ficou preso em um assunto ou conceito, escreva um artigo,


teste o código, etc. Quando escrevemos estamos aprendendo também. Abraços e sucesso Dev!


https://medium.com/trainingcenter/heran%C3%A7a-e-prot%C3%B3tipos-no-javascript-2c1e60e005a2

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

https://qastack.com.br/programming/9959727/proto-vs-prototype-in-javascript

https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/Objects/Object_prototypes


Linkedin:

linkedin.com/in/samuel-ferreira-da-costa-kail1999


GitHub:

https://github.com/kailera



Créditos da Capa: PixaBay

0
0

Comentários (0)

Usar programação para otimizar e melhorar os sistemas para todos.

Brasil