Herança de Protótipos - JavaScript
JavaScript suporta herança, permitindo que criemos novos tipos de objetos que, quando necessário, herdem funcionalidades de objetos já existentes. No entanto, é importante entender que a herança em JavaScript difere da herança em outras linguagens populares como Java, C++, e C#. Em JavaScript, a herança é uma herança de objetos (e não de classes ou tipos), também conhecida como herança de protótipos ou herança prototípica.
Para criar um objeto baseado em um protótipo, utilizamos a função Object.create()
const person = {
name: "",
age: 0,
print: function() {
console.log(`Name: ${this.name} Age: ${this.age}`);
}
};
const employee = Object.create(person); // employee utiliza o protótipo do objeto person
// obter o protótipo
console.log(employee.__proto__); // {name: "", age: 0, print: ƒ}
employee.name = "Tom";
employee.age = 39;
employee.print(); // Name: Tom Age: 39
Neste caso, o objeto employee
person
employee
person
employee
person
Adicionalmente, objetos podem definir suas próprias propriedades e métodos. Por exemplo:
const person = {
name: "",
age: 0,
print: function() {
console.log(`Name: ${this.name} Age: ${this.age}`);
}
};
const employee = Object.create(person);
employee.name = "Tom";
employee.age = 39;
employee.company = "Google"; // nova propriedade
// novo método
employee.work = function() {
console.log(`${this.name} works at ${this.company}`);
}
employee.print(); // Name: Tom Age: 39
employee.work(); // Tom works at Google
Neste caso, o objeto employee
company
work
Quando necessário, podemos redefinir métodos herdados:
employee.print = function() {
console.log(`Name: ${this.name} Age: ${this.age} Company: ${this.company}`);
}
employee.print(); // Name: Tom Age: 39 Company: Google
Aqui, a função print
const person = {
name: "",
age: 0,
print: function() {
console.log(`Name: ${this.name} Age: ${this.age}`);
}
};
const employee = Object.create(person);
employee.company = "";
// objeto manager herda o protótipo do objeto employee
const manager = Object.create(employee);
// redefinindo o método print
manager.print = function() {
console.log(`Name: ${this.name} Age: ${this.age}\nManager at ${this.company}`);
}
manager.name = "Bob";
manager.age = 43;
manager.company = "Microsoft";
manager.print(); // Name: Bob Age: 43
// Manager at Microsoft
Assim, criamos uma cadeia de protótipos: person-employee-manager
employee
person
manager
employee
Chamada de Métodos do Protótipo Base
Às vezes, pode ser necessário invocar métodos definidos no protótipo. Isso pode ser útil para reduzir duplicação de código, especialmente quando o código do método redefinido repete a lógica do método no protótipo. Ao obter o protótipo de um objeto, podemos chamar seus métodos usando a função call()
employee.print = function() {
this.__proto__.print.call(this); // chama a versão do método de person
// Object.getPrototypeOf(this).print.call(this); // outra forma de chamar
console.log(`Company: ${this.company}`);
}
employee.print(); // Name: Tom Age: 39
// Company: Google
Neste exemplo, no método print
employee
print
person
Verificação de Herança de Protótipos e Object.isPrototypeOf()
Usamos o método Object.isPrototypeOf()
const person = {
name: "",
print: ()=>console.log("Name:", this.name)
};
const user = {
name: "",
print: ()=>console.log("Name:", this.name)
};
// o objeto employee herda o protótipo de person
const employee = Object.create(person);
console.log(person.isPrototypeOf(employee)); // true
console.log(user.isPrototypeOf(employee)); // false
Aqui, o objeto employee herda o protótipo de person
person.isPrototypeOf(employee)
user
employee