1

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).

2
  • I think in a classic inheritance scenario, you will say base(name) when name of an person is to be set thru Employee ctor (assuming base class has ctor taking name as string). Same is achieved here with prototype inheritance... Commented Jan 13, 2014 at 13:52
  • It re uses Person constructor code and makes instance specific members of Person instance specific members of the to be created Employee. Funny that the book you mentioned doesn't do that. Maybe this answer can show why you should do this: stackoverflow.com/a/16063711/1641941 Commented Jan 13, 2014 at 15:11

2 Answers 2

4

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|
|------|
| ***  |
Sign up to request clarification or add additional context in comments.

2 Comments

Very detailed answer. Although Joe's answer is sufficient, I believe this is a better explanation for people new to JS inheritance.
I'd agree. That's a heck of an answer.
2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.