¿Cómo acceder a un método desde el prototipo principal en el niño como podemos con las clases?
En una clase, cuando tenemos un método en la clase principal, podemos acceder al mismo en la clase secundaria. En la forma prototipo de hacer lo mismo, no puedo acceder al método prototipo principal
con class :
class Person { constructor(name, id){ this.name = name; this.id = id; } printDetails (){ console.log(`Printing details in parent class :${this.name} : ${this.id}`); } } class Employee extends Person { constructor(name, id, salary){ super(name, id); this.salary = salary; } employeeInfo(){ // this will exist in the prototype of Employee class, not in the instance. return `${this.name} : ${this.id} : ${this.salary}` } } const a = new Employee('Mary', 1, 123456); // console.log(a.employeeInfo()) // a.printDetails();Con función y prototipo:
let PersonF = function(name, id){ this.name = name; this.id = id; } PersonF.prototype.getDetails = function(){ // Dont use arrow here, the this for the arrow is window, not the this of the object console.log(`Printing details in parent in function way :${this.name} : ${this.id}`); } let pers = new PersonF('Person', 111); // pers.getDetails(); let EmployeeF = function(name, id, salary){ PersonF.call(this, name, id); // this is same as super in class. here first param will take the this of the context and then other params this.salary = salary; } Object.setPrototypeOf(EmployeeF, PersonF.prototype); // This is same as extends in class. EmployeeF.prototype.printDetails = function(){ console.log(`${this.name} : ${this.id} : ${this.salary}`); } const emp = new EmployeeF('John', 1 , 10000000); // emp.printDetails(); emp.getDetails(); // Getting an error here.Puede asegurarse de que EmployeeF herede su prototipo de PersonF usando Object.create con PersonF s Prototype:
EmployeeF.prototype = Object.create(PersonF.prototype) let PersonF = function(name, id){ this.name = name; this.id = id; } PersonF.prototype.getDetails = function(){ console.log(`Printing details in parent in function way :${this.name} : ${this.id}`, this); // added log of `this` } let pers = new PersonF('Person', 111); let EmployeeF = function(name, id, salary){ PersonF.call(this, name, id); this.salary = salary; } EmployeeF.prototype = Object.create(PersonF.prototype) // create Employees Prototype from Persons EmployeeF.prototype.printDetails = function(){ console.log(`${this.name} : ${this.id} : ${this.salary}`); } const emp = new EmployeeF('John', 1 , 10000000) emp.getDetails();Esto también es (parte de) lo que hace Babel cuando se dirige a <IE10:
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }Tu problema es:
Object.setPrototypeOf(EmployeeF, PersonF.prototype); Este método está hecho para objetos que se usan como instancias y no para objetos que se usan como clases; en realidad establece el atributo __proto__ , por ejemplo, y no el atributo prototype de una clase.
Puedes ver esto en este polyfill:
Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) { obj.__proto__ = proto; return obj; } Luego, se puede acceder a getDetails de esta manera: EmployeeF.getDetails() (que llama en segundo plano a EmployeeF.__proto__getDetails() .
Te sugiero esto:
function Person(name) { this.name = name; } Person.prototype.print = function () { console.log('I am', this.name); } function Employee(name, id) { this.name = name; this.id = id; } // What has changed ! Employee.prototype = Object.create(Person.prototype); Employee.prototype.constructor = Person; Employee.prototype.work = function() { console.log(this.id, this.name, 'is working...'); } var e = new Employee('Michel', 43); e.print(); // 'I am Michel' El objetivo aquí es decir "El prototipo del prototipo de Empleado es el prototipo de Persona", es decir, Employee.prototype.prototype = Person.prototype .
¿Por qué prototipo.prototipo?
Porque el prototipo de Employee debe contener los métodos heredables de Employee, no los de Person; por lo que los métodos heredados de Person estarán en el PRÓXIMO prototipo en la cadena de prototipos.
Object.create(a_prototype); devuelve un objeto vacío, pero establece el prototipo de este objeto en a_prototype . Entonces, primero, creamos el prototipo de Employee en un objeto vacío, pero teniendo Person.prototype como su prototipo:
Employee.prototype = Object.create(Person.prototype); Ahora, solo queda un problema: ¡ Employee.prototype no tiene constructor! Luego, simplemente lo agregamos a través de:
Employee.prototype.constructor = Person; Gracias a esto, podemos ver que Employee hereda de Person a través de Employee.prototype.constructor . Para ver esto, simplemente intente imprimir una instancia de Person : el constructor está en person_instance.__proto__.constructor ; luego intente hacer lo mismo con un nuevo Employee , sin el código anterior: ¡sin constructor en el prototipo!
Esta es una solución simplificada de lo que hace TypeScript transpiler para convertir clases de ES6 a ES5:
Object.setPrototypeOf(Employee, Person); function PrototypeOfEmployee() { this.constructor = Employee; } PrototypeOfEmployee.prototype = Person.prototype; Employee.prototype = new PrototypeOfEmployee();