Todos nós sabemos que o JavaScript usa herança prototÃpica em vez do tipo clássico. Apesar de todos nós usarmos frameworks MVC avançados como AngularJs ou Ember.js, que fazem um ótimo uso da herança prototÃpica, ainda é fácil para nós ficarmos confusos sempre que alguém nos pede para explicar a herança em JavaScript.
O Mozilla tem um excelente guia sobre Herança e a cadeia de protótipos que é provavelmente o link para indicar alguém se fizer a temida pergunta … Quando se trata de herança, JavaScript só tem uma grande construção: objetos. Cada objeto possui um link interno para outro objeto denominado seu protótipo. Esse objeto de protótipo tem um protótipo próprio e assim por diante até que um objeto seja alcançado com null como seu protótipo, o elo final na cadeia de protótipo.
<b> Herdando propriedades e métodos em JavaScript </b>
Os objetos JavaScript são pacotes dinâmicos de propriedades e cada um tem um link para um objeto protótipo. Em JavaScript, qualquer função pode ser adicionada a um objeto na forma de uma propriedade e, nessa forma, é conhecida como método. Uma função herdada atua como qualquer outra propriedade. Quando uma função herdada é executada, o valor desta aponta para o objeto herdado.
<b> Criação de objetos que herdam propriedades </b>
Existem muitas abordagens para criar objetos que herdam de outros objetos em JavaScript, as abordagens mais comuns são usar a nova palavra-chave ou usar Object.create ()
<b> Construtor </b>
Um “construtor” em JavaScript é uma função chamada com o novo operador.
function Person(name) {
this.name = name;
}
Person.prototype.printName = function () {
console.log(this.name);
}
var me = new Person("Steven");
me.printName();
<b> Object.create () </b>
ECMAScript 5 introduziu Object.create. Chamar este método cria um novo objeto com o objeto de protótipo especificado e propriedades.
var a = { message: 'I am an a'};
var b = Object.create(a);
b.message = 'I am now a b';
É essencial entender o modelo de herança prototÃpico antes de escrever um código complexo que faça uso dele. Também é interessante para nós entender por que realmente nos importamos com herança em primeiro lugar. De acordo com Crockford, existem duas razões principais.
<b> Digite conveniência </b>
Queremos que o sistema de linguagem lance automaticamente referências de classes semelhantes. Isso é importante em linguagens fortemente tipadas, mas é irrelevante em linguagens vagamente tipadas como JavaScript, onde as referências de objeto nunca precisam ser convertidas.
<b> Reutilização de código </b>
É comum ter um conjunto de objetos, todos implementando exatamente o mesmo método. As classes permitem criar esses objetos a partir de um único conjunto de definições. Também é comum ter objetos semelhantes diferindo apenas em alguns métodos. A herança clássica é útil para isso, no entanto, a herança prototÃpica também pode ser muito útil para isso.
Como mostramos, em JavaScript, os objetos são facilmente estendidos. Um novo membro pode ser adicionado a um objeto por simples atribuição. Como os objetos em JavaScript são muito flexÃveis, é importante pensar de forma diferente sobre as hierarquias de classes. Hierarquias profundas são inadequadas. Hierarquias rasas são mais expressivas.
<b> Aulas em EcmaScript 6 </b>
EcmaScript 6 introduz suporte de linguagem para classes com <i> classes </i>, <i> construtores </i> e a palavra-chave <i> extend </i> para herança.
class Car {
constructor(make) {
this.make = make;
this.currentSpeed = 50;
}
}
class RaceCar extends Car {
constructor(make, topSpeed) {
super(make);
this.topSpeed = topSpeed;
}
goFast(){
this.currentSpeed = this.topSpeed;
}
}
let corvette = new RaceCar('Corvette', 150);
corvette.goFast();
O JavaScript é de natureza prototÃpica, portanto, a questão deve ser levantada: “Precisamos de herança clássica em JavaScript?” Não vou entrar em muitos detalhes aqui, Nicholas Zakas tem um excelente artigo sobre esse assunto. Como Nicholas menciona, a proposta de classe ECMAScript 6 atual é simplesmente uma nova sintaxe no topo dos padrões prototÃpicos atuais atualmente em uso comum em JavaScript. Herança funciona da mesma maneira que sempre, encadeamento de protótipo, métodos adicionados a protótipos e propriedades declaradas no construtor.