1

Below is a simple JavaScript inheritance example. Can we replace the line: Dog.prototype = new Animal();
with Dog.prototype = Animal.prototype?

I have tested in the browser, and they are giving me the same result. It's strange to me that why we need to create a new Animal object and assign it to Dog.prototype.

function Animal(age){
    this.age = age;
}

Animal.prototype.walk = function(){
     console.log("Walk"); 
}

function Dog(color, age){
    this.color = color;
    Animal.call(this, age)
}

Dog.prototype = new Animal();      //Why not Dog.prototype = Animal.prototype
Dog.prototype.constructor = Dog;


dog_b = new Dog("yellow", 9);
console.log("Age: " + dog_b.age +  " Color: " + dog_b.color );
dog_b.walk()
user1187968
  • 7,154
  • 16
  • 81
  • 152
  • "*It's strange to me that why we need to create a new Animal object*" - good intuition. You [should not use `new Animal` there indeed](https://stackoverflow.com/questions/12592913/what-is-the-reason-to-use-the-new-keyword-here). – Bergi Mar 18 '16 at 04:29

1 Answers1

2

In this particular case you can replace the lines for a simple reason:

function Dog(color, age) {
    this.color = color;
    Animal.call(this, age); // This line
}

Here, you're calling Animal's constructor with call providing it this thus establishing Animal's context manually. And so this inside function Animal will always refer to the Dog's object. That's why a new won't make a difference at all.

Strictly speaking, you're not actually doing proper prototypal inheritance. You can confirm that by doing:

dog_b.hasOwnProperty('age'); // => true

This is actually called constructor stealing where Dog stealing Animal's constructor. The walk method though is on Animal's ctor.

Which means the age property is on Dog itself and not on Animal. Why is that? Again, because you're establishing Animal's constructor context manually to be that of the Dog.

Edit:

In Javascript there are various ways of describing and attaining inheritance, and since this is not a place for writing a book I'll be quick.

What you're doing is called Parasitic Combination Inheritance (you don't have to remember the term). It's not wrong, it's simply another way of obtaining inheritance (which is prototypal only for functions that are on Animal.prototype). If it's working for you I'd say take it. If you really really want Animal's age to be on Animal, then you'll face problems when using constructors to obtain inheritance.

One way of doing this would be:

function inherit(o){
    function F(){}
    F.prototype = o;
    return new F();
}

var foo = {
    name: 'some'
}

var bar = inherit(foo); // bar.name refers to the object on foo

As you can see, prototypal inheritance is usually used for object literals (think angular's scope object).

mrahhal
  • 3,322
  • 1
  • 22
  • 41
  • So what is the right way to write the Dog() constructor without constructor stealing? – user1187968 Mar 18 '16 at 04:23
  • I'm not sure about your first line. Are you suggesting that both `Dog.prototype = new Animal();` and `Dog.prototype = Animal.prototype` are fine? Or even, that they do the same thing? – Bergi Mar 18 '16 at 04:31
  • I've never heard the term "constructor stealing". Given that `Dog` is supposed to inherit from `Animal`, it just would be a *[super](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Subclasses_and_superclasses) call*. – Bergi Mar 18 '16 at 04:32
  • @Bergi I'm simply saying that the end result of replacing that line would be the same (almost). And I don't think the term is common but it's written in a couple of books I've read. OP check the edit. – mrahhal Mar 18 '16 at 05:18