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 thegetDetails
function defined inPerson.prototype
because 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.prototype
becausethis
is nowTeacher.prototype
and its prototype isPerson.prototype
.The second call to
Teacher.prototype.getDetails()
invokes thePerson.prototype.getDetails()
functionYou need to bind
this
to make sure that value ofthis
insidePerson.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());