In the below code when I do console.log(teacher1.getDetails()); the property value shows undefined but when I do console.log(teacher1.personName) or console.log(teacher.mainSubject) it shows property value. What is happening here? What am I missing? Can somebody explain it please? And how to make it work?
let Person = function(personName, age) {
this.personName = personName;
this.age = age;
};
Person.prototype.getDetails = function() {
return `Person Name:${this.personName}. Age is ${this.age}.`;
};
//Child constructor function
let Teacher = function(personName, age, mainSubject) {
Person.call(this, personName, age);
this.mainSubject = mainSubject;
};
Teacher.prototype = Object.create(Person.prototype); //inheritance
Teacher.prototype.getDetails = function() {
return `${this.__proto__.getDetails()} Main subject is ${this.mainSubject}.`; //optionally invoke the parent method.
};
let teacher1 = new Teacher("Sakib", 35, "Physics");
console.log(teacher1.getDetails()); //invokes Teacher.getDetails() method (child's method).
CodePudding user response:
You need to implement getDetails method in the Teacher class like this:
Teacher.prototype.getDetails = function() {
return `${Person.prototype.getDetails.call(this)} Main subject is ${this.mainSubject}.`;
}
Your implementation doesn't work because of next: you call the parent method regarding parent's context which doesn't have values defined because in Teacher constructor you define values regarding the child context.
Person.call(this, personName, age);
Working example:
let Person = function(personName, age) {
this.personName = personName;
this.age = age;
};
Person.prototype.getDetails = function() {
return `Person Name:${this.personName}. Age is ${this.age}.`;
};
//Child constructor function
let Teacher = function(personName, age, mainSubject) {
Person.call(this, personName, age);
this.mainSubject = mainSubject;
};
Teacher.prototype = Object.create(Person.prototype); //inheritance
Teacher.prototype.getDetails = function() {
return `${Person.prototype.getDetails.call(this)} Main subject is ${this.mainSubject}.`; //optionally invoke the parent method.
};
let teacher1 = new Teacher("Sakib", 35, "Physics");
console.log(teacher1.getDetails()); //invokes Teacher.getDetails() method (child's method).
CodePudding user response:
Problems in your code:
this.__proto__.getDetails()doesn't directly calls thegetDetailsfunction defined inPerson.prototypebecause in the first invocation ofgetDetails()function,this.__proto__returnsTeacher.prototype. As a result,this.__proto__.getDetails()invokes itself, i.e.Teacher.prototype.getDetails()When
Teacher.prototype.getDetails()is called for the second time,this.__proto__now refers toPerson.prototypebecausethisis nowTeacher.prototypeand its prototype isPerson.prototype.The second call to
Teacher.prototype.getDetails()invokes thePerson.prototype.getDetails()functionYou need to bind
thisto make sure that value ofthisinsidePerson.prototype.getDetails()is correctYou shouldn't use
__proto__- its deprecated. UseObject.getPrototypeOf()to get a prototype of an object
Fixed Code:
let Person = function(personName, age) {
this.personName = personName;
this.age = age;
};
Person.prototype.getDetails = function() {
return `Person Name:${this.personName}. Age is ${this.age}.`;
};
let Teacher = function(personName, age, mainSubject) {
Person.call(this, personName, age);
this.mainSubject = mainSubject;
};
Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.constructor = Teacher;
Teacher.prototype.getDetails = function() {
const personPrototype = Object.getPrototypeOf(Object.getPrototypeOf(this));
return `${personPrototype.getDetails.call(this)} Main subject is ${this.mainSubject}.`;
};
let teacher1 = new Teacher("Sakib", 35, "Physics");
console.log(teacher1.getDetails());
