4. En el código siguiente, ¿cómo harías para que "homer"y "lisa" pudiesen tener la funcionalidad Person y Adult?
const Person = {
fullName () {
return `${this.name} ${this.lastname}`;
}
};
const Adult = {
isAdult () {
return this.age > 18;
}
};
const homer = {
name: "Homer",
lastname: "Simpson"
};
const lisa = {
name: "Lisa",
lastname: "Simpson"
};
Respuesta:
-
1️⃣ Como no queremos setear literalmente el prototype de estos objetos literales (se considera un antipatrón), podemos usar Spread Syntax para ampliar nuestros objetos literales, clonando aquellas propiedades (métodos incluidos) en los objetos homer y lisa (el clonado es suferficial [shallow-cloning], es decir, solo clona aquellas propiedades de primer nivel, en la primera capa digamos):
const Person = { fullName () { return `${this.name} ${this.lastname}`; } }; const Adult = { isAdult () { return this.age > 18; } }; const homer = { name: "Homer", age: 45, lastname: "Simpson", ...Person, // (1) ...Adult, }; const lisa = { name: "Lisa", age: 8, lastname: "Simpson", ...Person, ...Adult, }; console.log(homer.fullName()) // Homer Simpson console.log(homer.isAdult()) // true console.log(lisa.fullName()) // Lisa Simpson console.log(lisa.isAdult()) // false // 1: También podríamos unificar Person y Adult // en un objeto literal intermedio y // no propagar la dupla a lo largo del // codebase.2️⃣ Otra manera, sería hacer uso de clases JS y extender la clase Adult de Person (no existe herencia múltiple en Vanilla JS). Aunque es importante hacer ver que las clases JS solo son sugar-syntax para no tener que lidiar con su herencia basada en prototipos (___proto__):
class Person { constructor ({ name, lastname }) { this.name = name; this.lastname = lastname; } fullName () { return `${this.name} ${this.lastname}`; } }; class Adult extends Person { constructor ({ name, lastname, age }) { super({ name, lastname }) this.age = age; } isAdult () { return this.age > 18; } }; const homer = new Adult({ name: "Homer", lastname: "Simpson", age: 45 }); const lisa = new Adult({ name: "Lisa", lastname: "Simpson", age: 8 }); // (1) console.log(homer.fullName()) // Homer Simpson console.log(homer.isAdult()) // true console.log(lisa.fullName()) // Lisa Simpson console.log(lisa.isAdult()) // false // 1: No parece muy correcto semánticamente // instanciar a Lisa como "adulta". // Habría que trabajar la nomenclatura y // las relaciones entre las entidades para // que el código sea más expresivo y preciso // con sus detalles de implementación.3️⃣ Otra opción, si no queremos hacer declaraciones de clases, es usar composición, aunque de alguna manera nos obliga previamente a conocer detalles de la entidad acogida:
// [...] function Person ({ name, lastname, age }) { this.name = name; this.lastname = lastname; this.isAdult = new Adult({ age }); this.fullName = () => { return `${this.name} ${this.lastname}`; } }; function Adult ({ age }) { return this.isAdult = () => { return age > 18; } }; const homer = new Person({ name: "Homer", lastname: "Simpson", age: 45 }); const lisa = new Person({ name: "Lisa", lastname: "Simpson", age: 8 }); console.log(homer.fullName()) // Homer Simpson console.log(homer.isAdult()) // true console.log(lisa.fullName()) // Lisa Simpson console.log(lisa.isAdult()) // false
Por Héctor Villar Mozo