javascriptinheritanceprototype-chain

Javascript Prototype changed but still accessing old methods


I was learning inheritance and Prototype chaining. I was stuck after seeing this behaviour of resetting the constructor function's prototype inside the function itself. On instantiating

const Person = function (name,age) {
    this.name = name;
    this.age = age;
}
Person.prototype.calcAge = function () {
    console.log(`My age is ${2022-this.age}`);
}
const Student = function (name,age,course) {
    Person.call(this,name,age);
    this.course = course;
    Student.prototype = null; // This should set Student's Prototype to null and 
// thus should not let instance to access intro property.
}
Student.prototype.intro = function () {
    console.log(`I am ${this.name} and my course is ${this.course}`)
};


const mike = new Student("mike",2000,"cse");

mike.intro();

In the code above, the output is I am mike and my course is cse but while instantiating I did set Student.prototype = null; so how is mike instance still accessing intro method.


Solution

  • At the moment you call new, the prototype object is taken from Student.prototype and used to create this. So at that moment the proto of this is the object that Student.prototype references.

    It is that proto reference that is later used to find the definition of intro. It is found via Object.getPrototypeOf(mike), not via Student.prototype. The latter only serves for future constructions.

    By setting Student.prototype to null, you only determine what will happen with the next use of new Student. But for the instance that was already created, it comes too late. Object.getPrototypeOf(this) (when in the constructor's execution), will still refer to the original prototype object.

    Here some extra console.log to illustrate that point:

    const Person = function (name,age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.calcAge = function () {
        console.log(`My age is ${2022-this.age}`);
    }
    const Student = function (name,age,course) {
        Person.call(this,name,age);
        this.course = course;
        // true:
        console.log(Student.prototype === Object.getPrototypeOf(this));
    
        Student.prototype = null; 
        // false:
        console.log(Student.prototype === Object.getPrototypeOf(this));
    }
    
    Student.prototype.intro = function () {
        console.log(`I am ${this.name} and my course is ${this.course}`)
    };
    
    const mike = new Student("mike",2000,"cse");
    // true:
    console.log(Object.getPrototypeOf(mike).hasOwnProperty("intro"));
    
    mike.intro();