Search code examples
javascriptinheritanceprototype

Prototype chain messes up while inheriting


This is my code

const Person = function(firstName, birthYear){
    this.firstName = firstName;
    this.birthYear = birthYear;
}

Person.prototype.calcAge = function(){
    console.log(2022 - this.birthYear);
}

const Student = function(firstName, birthYear, course){
    Person.call(this, firstName, birthYear);
    this.course = course;
}

Student.prototype = Object.create(Person.prototype);

Student.prototype.introduce = function(){
    console.log(`Hi I am ${this.firstName}, and I study ${this.course}`);
}

const vikash = new Student('Vikash', 2005, 'Computer science');

console.dir(Student.prototype.constructor);

I'm learning inheritance in JavaScript and all I'm doing is setting up the Student's prototype with an object that has it's proto as the Person's prototype.

I thought the console.log() will give me the Student constructor as the output.. But, to my surprise, the output I got is the Person constructor.. Why is it so?


Solution

  • Just after you set up a constructor function Student, its prototype has the default value of .constructor (and it's Student) as expected.

    However, you overwrite this default value with this specific line

    Student.prototype = Object.create(Person.prototype);
    

    To verify it, consider your code without this line (and without the prototype chain which you want)

    const Person = function(firstName, birthYear){
        this.firstName = firstName;
        this.birthYear = birthYear;
    }
    
    Person.prototype.calcAge = function(){
        console.log(2022 - this.birthYear);
    }
    
    const Student = function(firstName, birthYear, course){
        Person.call(this, firstName, birthYear);
        this.course = course;
    }
    
    Student.prototype.introduce = function(){
        console.log(`Hi I am ${this.firstName}, and I study ${this.course}`);
    }
    
    const vikash = new Student('Vikash', 2005, 'Computer science');
    
    console.log(Student.prototype.constructor);

    It seems then that you either have a correct proto chain or the correct constructor reference.

    This is why it's up to you to manually fix the code to have both

    const Person = function(firstName, birthYear){
        this.firstName = firstName;
        this.birthYear = birthYear;
    }
    
    Person.prototype.calcAge = function(){
        console.log(2022 - this.birthYear);
    }
    
    const Student = function(firstName, birthYear, course){
        Person.call(this, firstName, birthYear);
        this.course = course;
    }
    
    Student.prototype = Object.create(Person.prototype);
    Student.prototype.constructor = Student;
    
    Student.prototype.introduce = function(){
        console.log(`Hi I am ${this.firstName}, and I study ${this.course}`);
    }
    
    const vikash = new Student('Vikash', 2005, 'Computer science');
    
    console.log(Student.prototype.constructor);

    This way you have both the proto chain and the constructor reference you expect.