18 de mai de 2020 - 4 min de leitura
Tudo é objeto?
Herança e cadeia de protótipos
Introdução
Acho que o ditado mais famoso envolvendo JavaScript é aquele que diz:
Tudo é um objeto!
Mas será que é mesmo?
Vamos sub-dividir o JavaScript em dois tipos de dados, sendo:
- Primitivos
- Objetos
Primitivos
Segundo nosso bom e velho MDN, existem 6 tipos de dados primitivos no JavaScript:
Com exceção de null
e undefined
todos são objetos! :tada:
Objetos
O JavaScript conta com uma série de Objetos pré-definidos que podem ser usados por nós para trabalhar dados, mas também podemos utilizar de recursos como um construtor de objetos e criar nossos próprios objetos.
Um exemplo de um construtor pré-definido é o Array:
const arr = []; // Instância do objeto Array
Array.prototype // [constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
Construtor e Instâncias em JavaScript
A Programação Orientada a Objetos faz uso constante de objetos (sério?), propriedades e métodos. Onde esses objetos interagem entre sí para formar aplicações complexas.
Imagine que vamos criar uma pessoa utilizando um objeto simples:
const maicon = {
name: 'Maicon Silva',
yarnOfBirth: 1995,
job: 'developer',
};
O que podemos fazer para simplificar a criação de pessoa
no nosso código é criar um objeto especial Person
, que é reponsável por receber as propriedades que uma pessoa deve ter e cria-la para nós. Isso também é conhecido como Classe em POO, mas no JavaScript nós podemos chamar de Construtor ou Protótipo, e com base nesse construtor nós criamos quantas pessoas quisermos.
function Person(name, yarnOfBirth, job) {
this.name = name;
this.job = job;
this.yarnOfBirth = yarnOfBirth;
}
const Maicon = new Person('Maicon', 1995, 'developer'); // Person {name: "Maicon", job: "developer", yarnOfBirth: 1995}
A partir desse momento, todas as pessoas criadas são instâncias do nosso construtor Person
.
Herança
Em termos simples, herança é quando um objeto é baseado em outro objeto, obtendo acesso à propriedades e métodos do objeto base.
Agora além de pessoa, vamos criar um atleta. Mas um atleta assim como uma pessoa possui um nome, um ano de nascimento, um emprego, além de seus métodos e propriedades particulares como se ele é um atleta olímpico, quantas medalhas possui etc. Então o que podemos fazer é usar herança.
Dessa forma, fazemos com que o atleta herde propriedades e métodos inicialmente contidos no construtor Person
.
Herança: Protótipos
A herança em JavaScript é baseada em protótipos. Na prática isso significa que todo objeto em JavaScript possui uma propriedade chamada prototype
que possibilita a herança no JS.
Para que qualquer instância de Person
herde seus métodos ou atributos precisamos adiciona-los ao prototype de Person
.
function Person(name, yarnOfBirth, job) {
this.name = name;
this.job = job;
this.yarnOfBirth = yarnOfBirth;
};
Person.prototype.calculateAge = function() {
console.log(2020 - this.yarnOfBirth);
};
const Maicon = new Person('Maicon', 1995, 'developer'); // Person {name: "Maicon", job: "developer", yarnOfBirth: 1995}
Maicon.calculateAge(); // 25
Dessa forma Maicon
herda calculateAge e pode executa-la em seu contexto. Isso faz com que qualquer objeto instanciado através de Person
herde o método calculateAge.
Herança: Cadeias de Protótipos
Person
é um objeto e todos os objetos em JavaScript são descendentes do Object. Todos os objetos herdam métodos e propriedades de Object.prototype
.
Isso é o que faz a cadeia de protótipos funcionar. Quando acessamos um método ou propriedade de um objeto o JavaScript primeiro tenta encontrar o método no objeto exato, mas se não encontra-lo ele olha para o protótipo do objeto, que é o protóripo de seu "pai". Com isso ele sobe a cadeia de protótipos, e isso continua até que não haja mais protótipos para análisar, que é nulo. E nulo não possui protótipo, então undefined é retornado.
Conclusão
Vimos que nem tudo no JavaScript é um objeto, pois null
e undefined
não possuem caracteristicas de um objeto.
Também vimos:
- Vimos que variáveis inicializadas através de construtores pré-definidos no JS herdam métodos que podemos usar, como no caso do arrays que herdam métodos como map, filter, pop etc;
- Todo objeto no JavaScript possui uma propriedade
prototype
, que possibilita a herança; - A propriedade
prototype
de um objeto é onde adicionamos métodos e atributos que queremos que outros objetos herdem; - A propriedade
prototype
de um objeto não é o protótipo do construtor em sí, mas é o protótipo de todas as instâncias que são criadas através dele; - Quando o JavaScript não encontra um método que foi chamado na instância do objeto atual, ele sobe na cadeia de protótipos até que método seja enconstrado ou que undefined seja retornado;
Dicas, sugestões, conselhos ou melhorias? Você pode entrar em contato comigo pelas minhas redes ou abrir uma PR no repositório aqui.