Arju Aman
Arju Aman

Reputation: 412

".. is not a function" Error when creating a method of Child Class using prototype inheritance

I'm learning JavaScript prototyping. Here Employee is parent, I inherited from it in my Programmer prototype, but when I try to run the favoriteLanguage method of my child prototype(i.e Programmer), it's showing that favoriteLanguage is not a function. I tried reading from Mozilla documentation, but I couldn't understand if the stuff was relevant or not! Can anybody help me in simple terms please!

Edit: I know I can use class, but I want to learn why it's not working in this case!

Here's the code:

function Employee(givenName, givenExperience, givenDivision){
    this.name = givenName;
    this.experience = givenExperience;
    this.division = givenDivision;
}

Employee.prototype.slogan=function(){
    return `I am ${this.name} and this company is the best`;
}

Employee.prototype.joiningYear=function(){
    return 2020 - this.experience;
}

function Programmer(givenName, givenExperience, givenDivision, language, github){
    Employee.call(this,givenName, givenExperience, givenDivision);
    this.language = language;
    this.github = github;
}

Programmer.prototype.favoriteLanguage = function(){   //Error part
    if (this.language == 'python'){
        return 'Python';
    }
    else{
        return 'JavaScript';
    }
}

Programmer.prototype = Object.create(Employee.prototype);
Programmer.prototype.constructor = Programmer;

//Object.setPrototypeOf(Programmer.prototype, Employee.prototype);

let arju = new Programmer("Arju Aman",0,"Developer","javaScript","arjuaman");

console.log(arju);
// console.log(arju.joiningYear());
// console.log(arju.slogan());

console.log(arju.favoriteLanguage());   //called here

Upvotes: 2

Views: 735

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074385

The problem is you're adding a property to the default Programmer.prototype object:

Programmer.prototype.favoriteLanguage = function(){
    // ...
}

...but a moment later you're completely replacing that object with a new object:

Programmer.prototype = Object.create(Employee.prototype);

The new object won't have the property you added to the old one.

To fix it, just move the Programmer.prototype = statement above the statement adding a property to it:

function Employee(givenName, givenExperience, givenDivision){
    this.name = givenName;
    this.experience = givenExperience;
    this.division = givenDivision;
}

Employee.prototype.slogan=function(){
    return `I am ${this.name} and this company is the best`;
}

Employee.prototype.joiningYear=function(){
    return 2020 - this.experience;
}

function Programmer(givenName, givenExperience, givenDivision, language, github){
    Employee.call(this,givenName, givenExperience, givenDivision);
    this.language = language;
    this.github = github;
}

// *** Moved
Programmer.prototype = Object.create(Employee.prototype);
Programmer.prototype.constructor = Programmer;

Programmer.prototype.favoriteLanguage = function(){
    if (this.language == 'python'){
        return 'Python';
    }
    else{
        return 'JavaScript';
    }
}

let arju = new Programmer("Arju Aman",0,"Developer","javaScript","arjuaman");

console.log(arju);

console.log(arju.favoriteLanguage());

However, you mentioned you're learning JavaScript. Since 2015, JavaScript has had a much simpler way of defining constructor functions and the prototypes they assign to new instances: class syntax:

class Employee {
    constructor(givenName, givenExperience, givenDivision) {
        this.name = givenName;
        this.experience = givenExperience;
        this.division = givenDivision;
    }

    slogan() {
        return `I am ${this.name} and this company is the best`;
    }

    joiningYear() {
        return 2020 - this.experience;
    }
}

class Programmer extends Employee {
    constructor(givenName, givenExperience, givenDivision, language, github) {
        super(givenName, givenExperience, givenDivision);
        this.language = language;
        this.github = github;
    }

    favoriteLanguage() {
        if (this.language == "python"){
            return "Python";
        } else{
            return "JavaScript";
        }
    }
}

let arju = new Programmer("Arju Aman", 0, "Developer", "javaScript", "arjuaman");

console.log(arju);

console.log(arju.favoriteLanguage());

The new syntax still does much the same thing (this is still prototypical inheritance, it still creates a constructor function with a prototype property that defines the object that new X will assign the new object, etc.) but it's much simpler to use, particularly when inheriting. It also supports private fields and methods now; the following three proposals have all landed in the specification:

Having truly private information without these is possible, but much more cumbersome.

Upvotes: 3

Related Questions