Prototypal inheritance
Javascript tem suas complicações de sintaxe e o monstruoso new
apenas por jogo de marketing na época que o Java estava em alta. Mesmo o funcionamento sendo absolutamente diferente, desenvolvedores costumam achar que a herança e as instâncias podem funcionar iguais às do Java. Há um grande número de posts e artigos que explicam muito bem isto, inclusive este aqui do Douglas Crockford(Post muito antigo) já dá para ter uma ideia do que estamos falando.
E olha.. nenhum tipo de ‘new’
// Person constructor
const Person = Object.create(null);
Person.whoAmI = function () {
return 'Person';
};
Person.name = "Person";
Person.attributes = function () {
return this;
};
Person.super = function() {
return Object.getPrototypeOf(this); // Retorna o objeto superior à este
};
// Adult constructor
const Adult = Object.create(Person);
Adult.whoAmI = function () {
return 'Adult';
};
// Child constructor
const Child = Object.create(Adult);
Child.whoAmI = function () {
return 'Child';
};
// Baby constructor
const Baby = Object.create(Child);
Baby.whoAmI = function () {
return 'Baby';
};
Baby.getName = function () {
return this.name;
};
// john is an instance of Baby
const john = Object.create(Baby);
john.name = "John";
john.whoAmI = function () {
return 'John Smith';
};
console.log(john.name); // "John
// lilJohn is an instance of john
const lilJohn = Object.create(john);
console.log(lilJohn.super().name); // "John"
// janna is an instance of Baby
const janna = Object.assign(Object.create(Baby), john);
janna.name = "Janna";
console.log(janna.name); // "Janna"
console.log(janna.super().name) //"Person"
console.log(Object.getPrototypeOf(janna) === Object.getPrototypeOf(john)); // true
console.log(john.super().super().super().whoAmI()); // "Person"
console.log(john.super().super().super().whoAmI()); // "Adult"
console.log(john.super().super().whoAmI()); // "Child"
console.log(john.super().whoAmI()); // "Baby"
console.log(john.whoAmI()) // "John Smith
Entenda o conceito e você irá longe
Estude o código acima.. Veja o que está acontecendo por trás dos panos. Eu garanto que não será tão assustado quanto parece. Neste caso de uso o instanceof
e o atributo prototype
explicitamente não são chamados, e nem precisa. O grande Object.create
já toma conta disso tudo sem a gente ver.
Referência do Doc
// Polyfill do Object.create
if (typeof Object.create != 'function') {
Object.create = (function() {
var Temp = function() {};
return function (prototype) {
if (arguments.length > 1) {
throw Error('Second argument not supported');
}
if(prototype !== Object(prototype) && prototype !== null) {
throw TypeError('Argument must be an object or null');
}
if (prototype === null) {
throw Error('null [[Prototype]] not supported');
}
Temp.prototype = prototype; // Uso do prototype
var result = new Temp(); // Uso do new
Temp.prototype = null;
return result;
};
})();
}
Orientação a objetos!
Afinal de contas, a linguagem dinâmica consegue sim replicar os conceitos teóricamente de outro mundo de outras linguagens. Leia bastante livros, siga os gurus nas redes sociais e veja muito código no Github. Com o tempo, isto virá na cabeça com um estalo de dedos. Um abraço!