Object Oriented Programming: Add Methods After Inheritance

Hi there, please help me understand this.

function Animal() { }
Animal.prototype.eat = function() { console.log("nom nom nom"); };

function Dog() { }
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype = {
    constructor : Dog, 
    bark(){
        console.log( "Woof!");
    }
}

let beagle = new Dog();

console.log(beagle.eat());

The above-written code generates a TypeError: beagle.eat is not a function.

But when I write the same code as this

function Animal() { }
Animal.prototype.eat = function() { console.log("nom nom nom"); };

function Dog() { }
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function (){
    console.log("Woof!");
}

let beagle = new Dog();
console.log(beagle.eat());

It works absolutely fine.

My question is that why inheritance doesn’t work in the former case???

Link to this challenge - https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance

Reason for my confusion –

I want to know if I have to add several methods unique to the Dog Object, do I have to write each unique methods separately like this?

Dog.prototype.bark = function (){
    console.log("Woof!");
}

Dog.prototype.method2 = function (){
    console.log("Woof!");
}

Dog.prototype.method3 = function (){
    console.log("Woof!");
}

Dog.prototype.method4 = function (){
    console.log("Woof!");
}

I had read in an earlier chapter that

A more efficient way is to set the `prototype` to
 a new object that already contains the properties.
 This way, the properties are added all at once

How could I use inheritance as well as set the prototype to a new object in this case?

What exactly is your question? Can you post a link to the challenge?

function Animal() { }
Animal.prototype.eat = function() { console.log("nom nom nom"); };

function Dog() { }
Dog.prototype = Object.create(Animal.prototype);
/*Dog.prototype = {
    constructor : Dog, 
    bark(){
        console.log( "Woof!");
    }
}

let beagle = new Dog();

console.log(beagle.eat());
*/
/*The above written code generates TypeError: beagle.eat is not a function. Why inheritance doesn't work in this case???*/


/* But when I write the same as this, it works. */

Dog.prototype.constructor = Dog;
Dog.prototype.bark = function (){
    console.log("Woof!");
}

let beagle = new Dog();
console.log(beagle.eat());

Ok. Can you post a link to the challenge please?


Dog.prototype = {
    constructor : Dog,
    bark : function(){
        console.log("Woof");
    }
}

This does not connect back to the Animal prototype at all, so the Dog does not know how to .eat().

But I have written this before this declaration

Dog.prototype = Object.create(Animal.prototype);

So, it should inherit the methods defined in the Animal supertype? No?

If not, can you explain how can I write this piece of code inside Dog.prototype object?

You are entirely replacing the prototype with that assignment, removing the connection to the Animal prototype.

Here we go, I found the link to the challenge.

Take a look a this to see where you have erased the connection to the parent Animal.

function Animal() { }
Animal.prototype.eat = function() { console.log("nom nom nom"); };

function Dog() { }

// Only change code below this line

// Correct prototype
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bork = function (){
    console.log("Warf!");
};

console.log("Prototype referencing 'Animal'");
console.log(Object.getPrototypeOf(Dog.prototype));
console.log(".eat  : " + Dog.prototype.eat);
console.log(".bork : " + Dog.prototype.bork);

// Incorrect prototype
Dog.prototype = {
    constructor: Dog, 
    bork: function() {
        console.log( "Warf!");
    }
};

console.log("\nPrototype overwriting reference to 'Animal'");
console.log(Object.getPrototypeOf(Dog.prototype));
console.log(".eat  : " + Dog.prototype.eat);
console.log(".bork : " + Dog.prototype.bork);

// Only change code above this line

let beagle = new Dog();

I got your point sir. I want to know if I have to add several methods unique to the Dog Object, do I have to write each unique methods separately like this?

Dog.prototype.bark = function (){
    console.log("Woof!");
}

Dog.prototype.method2 = function (){
    console.log("Woof!");
}

Dog.prototype.method3 = function (){
    console.log("Woof!");
}

Dog.prototype.method4 = function (){
    console.log("Woof!");
}

I had read in an earlier chapter that

A more efficient way is to set the `prototype` to
 a new object that already contains the properties.
 This way, the properties are added all at once

How could I use inheritance as well as set the prototype to a new object in this case?

Ah, I see what you mean.

I do not know if this is idiomatic, but:

function Animal() { }
Animal.prototype.eat = function() { console.log("nom nom nom"); };

function Dog() { }

// Only change code below this line

// Correct prototype
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bork = function (){
    console.log("Warf!");
};

console.log("Prototype referencing 'Animal'");
console.log(Object.getPrototypeOf(Dog.prototype));
console.log(".eat  : " + Dog.prototype.eat);
console.log(".bork : " + Dog.prototype.bork);

// Incorrect prototype
Dog.prototype = {
    constructor: Dog, 
    bork: function() {
        console.log( "Warf!");
    }
};

console.log("\nPrototype overwriting reference to 'Animal'");
console.log(Object.getPrototypeOf(Dog.prototype));
console.log(".eat  : " + Dog.prototype.eat);
console.log(".bork : " + Dog.prototype.bork);

// Repaired prototype
Dog.prototype = {
    constructor: Dog, 
    bork: function() {
        console.log( "Warf!");
    }
};
Object.setPrototypeOf(Dog.prototype, Animal.prototype);

console.log("\nRepaired prototype overwriting reference to 'Animal'");
console.log(Object.getPrototypeOf(Dog.prototype));
console.log(".eat  : " + Dog.prototype.eat);
console.log(".bork : " + Dog.prototype.bork);

// Only change code above this line

let beagle = new Dog();

I am sorry if I am annoyingly asking the same question again and again. I am really trying to understand. Can you explain why Object.create is not enough in this case?

Because right after

Dog.prototype = Object.create(Animal.prototype);

you are replacing everything in Dog.protoype with

Dog.prototype = {
    constructor: Dog, 
    bork: function() {
        console.log( "Warf!");
    }
};

which destroys the connection between Dog and Animal.

Did you run the code I attached? It shows that these different approaches result in different behaviour when you call Object.getPrototypeOf(Dog.prototype).

1 Like

I ran it and it worked as expected. I think I have understood it. Thanks a lot for your quick response sir. It really helped.

1 Like