JavaScript Inheritance

I had an interview for a web developer position several days ago. I was asked about some basic JavaScript questions, like inheritance. Unfortunately I didn’t make it through as I only know there is something about “prototype”, but did not fully understand it. Now it is time to make it clear.

Talking about inheritance, JavaScript is a little bit different as it is not a typical object-oriented programming language. It is all about “prototype” rather than “class”. For example, we have a Person constructor, or “class”:

function Person(fn, ln, a, g) {
    this.firstName = fn;
    this.lastName = ln;
    this.age = a;
    this.gender = g;
}

Except for all the properties, we want to have a sayName method to get the full name, so we add this method on Person.prototype, which will be shared for every instance. Notice that I cannot write this.prototype in the constructor, because the prototype property will be automatically created after creating the constructor (and every other function). I made this mistake during the interview. 😦

function Person(fn, ln, a, g) {
    this.firstName = fn;
    this.lastName = ln;
    this.age = a;
    this.gender = g;
 // this.prototype = ... // NO! prototype is undefined yet
}

// modify prototype after the constructor is created
Person.prototype.sayName = function() {
    console.log(this.firstName + " " + this.lastName);
}

Then we want one more Employee type inherit from the Person, and has its own office property.


function Employee(o) {
    // inherit from Person
    // ... How?

    // create its own property
    this.office = o;
}

How?

According to Professional JavaScript for Web Developers by Nicholas C. Zakas, and MDN web docs, we can implement the inheritance like below:

First, call parent’s constructor to inherit the properties.

function Person(fn, ln, a, g) {
    this.firstName = fn;
    this.lastName = ln;
    this.age = a;
    this.gender = g;
}

Person.prototype.sayName = function() {
    console.log(this.firstName + " " + this.lastName);
}

function Employee(fn, ln, a, g, o) {
    // inherit from Person
    Person.call(this, fn, ln, a, g);

    // create its own property
    this.office = o;
}      

We use the call function to call parent’s constructor inside child’s constructor, and the first parameter specifies the value of this when running the function, which now is the Employee constructor.

We have already inherited all parent’s properties in the constructor, then we need to inherit parent’s methods on its prototype, like the sayName function. The Object.create()function is exactly designed for this.

function Person(fn, ln, a, g) {
    this.firstName = fn;
    this.lastName = ln;
    this.age = a;
    this.gender = g;
}

Person.prototype.sayName = function() {
    console.log(this.firstName + " " + this.lastName);
}

function Employee(fn, ln, a, g, o) {
    // inherit properties from constructor
    Person.call(this, fn, ln, a, g);

    // create its own property
    this.office = o;
}     

// inherit methods from prototype
Employee.prototype = Object.create(Person.prototype); 

Now the child type Employee has inherited all the properties and methods from parent type Person, even include one thing we do not need to inherit: constructor. So we should set it back.

function Person(fn, ln, a, g) {
    this.firstName = fn;
    this.lastName = ln;
    this.age = a;
    this.gender = g;
}

Person.prototype.sayName = function() {
    console.log(this.firstName + " " + this.lastName);
}

function Employee(fn, ln, a, g, o) {
    // inherit properties from constructor
    Person.call(this, fn, ln, a, g);

    // create its own property
    this.office = o;
}     

// inherit methods from prototype
Employee.prototype = Object.create(Person.prototype);

// parent constructor is also inherited
console.log(Employee.prototype.constructor === Employee);
// false

// so set child constructor back
Employee.prototype.constructor = Employee;

console.log(Employee.prototype.constructor === Employee);
// true

Done! Let’s test it.

function Person(fn, ln, a, g) {
    this.firstName = fn;
    this.lastName = ln;
    this.age = a;
    this.gender = g;
}

Person.prototype.sayName = function() {
    console.log(this.firstName + " " + this.lastName);
}

function Employee(fn, ln, a, g, o) {
    // inherit properties from constructor
    Person.call(this, fn, ln, a, g);

    // create its own property
    this.office = o;
}     

// inherit methods from prototype
Employee.prototype = Object.create(Person.prototype);

// set child constructor back
Employee.prototype.constructor = Employee;

// test
var bob = new Employee("Bob", "Smith", 28, "male", "Web");
bob.sayName(); // Bob Smith 

It works! But too late.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s