Question

I am trying to understand this piece of code and am wondering why we have a call to super constructor function in the sub "class" constructor function:

function Person(name) {
   this.name = name;
}
// Other properties on Person prototype here...

function Employee(id, name) {
    Person.call(this, name);   // Why do we have to do this?
    this.id = id;
}
Employee.prototype = Object.create(Person.prototype);
// Other properties on Employee prototype here...

1) Why do we have Person.call(this, name) ? In "Secrets of the Javascript Ninja", they do prototype inheritance WITHOUT calling the super constructor (the rest of the code is the same, except Object.create , but I understand why that is needed).

Was it helpful?

Solution

So this is the prototype chain of your Employee (and Person) without the line Person.call(this,name):

|Person|                       |Employee|
|------|                       |--------|
|name  |                       |wage    |
|sex   |                       |id      |

   |                               |
   |                               |
   v                               v

|Person Prototype|             |Employee Prototype|
|----------------|             |------------------|
|walk()          |  <--------  |work()            |
|eat()           |             |goOnStrike()      |
|sleep()         |

   |
   |
   v

|Object|
|------|
| ***  |

Every time, you request a property of an employee, JavaScript looks for that property by traveling down the prototype chain. If you write this:

var employee = new Employee(1, "Jack White");
employee.walk();

JavaScript will look in employee, than in employee.[[prototype]] and then in employee.[[prototype]].[[prototype]] (following the arrow directions in the diagram) until it finds the property walk.

As you can see, if you request the property name, JavaScript will not find it, because it is not in the prototype chain of employee. So you have to make sure, to also "copy" local properties like name and sex.

You do this by calling the constructor of Person with the context of the current Employee:

function Employee(id, name) {
    Person.call(this, name);
    this.id = id;
}

which does essentially the same as if you would just copy all the code from inside of the Person constructor in the Employee constructor:

function Employee(id, name) {
    this.name = name; //copied from Person
    this.id = id;
}

This results in the following setup and an employee with a name property:

|Person|                       |Employee|
|------|                       |--------|
|name  |                       |wage    |
|sex   |                       |id      |
                               |name    |
                               |sex     |

   |                               |
   |                               |
   v                               v

|Person Prototype|             |Employee Prototype|
|----------------|             |------------------|
|walk()          |  <--------  |work()            |
|eat()           |             |goOnStrike()      |
|sleep()         |

   |
   |
   v

|Object|
|------|
| ***  |

OTHER TIPS

Not calling the super's constructor implies that the subclass has some knowledge of the superclass's behavior: that's the opposite of encapsulation. It shouldn't know if the parent class needs or doesn't need any kind of 'setup' in its constructor. To be safe, it should simply call it and carry on.

For example, if Person always had to initialize a bunch of properties on instantiation, and Employee didn't call Person constructor, Employee instance operations that rely on Person properties/methods may not behave properly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top