Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Exploring OOPS - JavaScript Style: Part 2 - Inheritance

3.09/5 (8 votes)
2 Aug 2008BSD5 min read 1   88  
This article discusses Inheritance in JavaScript.

Introduction

In the second article of the series of "Exploring OOPS - JavaScript Style", we look at how inheritance is implemented in JavaScript.

Note: This article is an adaptation (may be a mirror) of the article originally posted at Edujiniā„¢ Eduzineā„¢ here.

All the three articles of the series are listed below:

Inheritance can be described as reusability by virtue of heritage. An inherited data-type automatically obtains the functionality defined in the data-types from which it inherits.

JavaScript supports single inheritance, i.e., you can inherit from maximum one type. Also, it does not support the concept of interface introduced in languages like Java, C# to support multiple inheritance. In JavaScript, what we have is instance-inheritance (or runtime inheritance) rather than class-inheritance (or compile-time inheritance), making inheritance more powerful than probably any other language around (barring the ones like Smalltalk)!

Getting Started

In Part 1, we defined UserProfile with username and password. In this article, we create EmployeeProfile that inherits from UserProfile and adds employeeID. It also reimplements (override, if you like to use that word) authenticate method.

EmployeeProfile Definition

We start with defining EmployeeProfile with employeeID besides earlier properties. Create a file EmployeeProfile.js with the following code:

JavaScript
/**
 * Part of the Eduzine (http://eduzine.edujini-labs.com) Articles.
 *
 * Downloads available at http://downloads.edujini-labs.com
 *
 * (C) 2008, Edujini Labs Pvt Ltd
 * http://www.edujini-labs.com
 */

function EmployeeProfile(username, password, employeeID)
{
  this.username = username;
  this.password = password;
  this.employeeID = employeeID;
}

The next step is to mark it inherited from UserProfile. For this, we need to work with the property prototype that is always available to us whenever we declare a function. (Note that all functions can be used as constructor.) Add the following additional code at the end of the code above:

JavaScript
EmployeeProfile.prototype = new UserProfile();

Note the following:

  • The inheritance is defined not through the data-type UserProfile but through its instance.
  • The instance of UserProfile has been created without passing any parameters to the method.

Testing the Definition

So, it's time to test the definition so far... Let's create EmployeeProfile.html with the following content:

HTML
<html>
  <head>
    <title>OOPS in JavaScript- Encapsulation</code>
    <script language="'javascript'" type='text/javascript' src='UserProfile.js'></script>
    <script language="'javascript'" type='text/javascript' src='EmployeeProfile.js'></script>
    <script language="'javascript'" type='text/javascript'>
      /**
       * Part of the Eduzine (http://eduzine.edujini-labs.com) Articles.
       *
       * Downloads available at http://downloads.edujini-labs.com
       *
       * (C) 2008, Edujini Labs Pvt Ltd
       * http://www.edujini-labs.com
       */
      function validateUser()
      {
        var eid = document.getElementById('i').value;
        var uname = document.getElementById('u').value;
        var pwd = document.getElementById('p').value;

        var e = document.getElementById('result');

        var ep = new EmployeeProfile(uname, pwd, eid);
        e.innerHTML = 'Username: ' + ep.username
          + '<br/>Password: ' + ep.password
          + '<br/>EmployeeID: ' + ep.employeeID
          + '<br/>Authenticate: ' + ep.authenticate();
      }
    </script>
  </head>
  <body>
  Employee ID: <input type='text' name='i' id='i' />
  <br/>
  Username: <input type='text' name='u' id='u' />
  <br/>
  Password: <input type='password' name='p' id='p' />
  <br/>

  <button onclick='validateUser(); return false;'>Login</button>

  <div id='result'></div>

  </body>
</html>

I think the code is self explanatory. What we get is not only the three properties but also automatic definition of authenticate method for EmployeeProfile. After all, that's what inheritance is all about. In the definition of EmployeeProfile, we never mention about it but it is automatically available to it through its parent object UserProfile.

instanceof Operator

We'll explore method overriding and other complex (unexplored, not mentioned so far) things in a while. We take a short while to look at instanceof operator.

It is a binary operator. The left operand is the object-reference and the right operand is the function-definition (data-type reference). The operator returns a boolean value indicating whether the object is an instance of the corresponding type or not.

JavaScript
if(ep instanceof UserProfile)
{
  alert('ep is an instance of type UserProfile');
} else
{
  alert('ep is NOT an instance of type UserProfile');
}

You can add this code to the method validateUser. In our case, it must return true. Similarly, obj instanceof Object for any non-null value for obj will return true.

Method Reference and Optimization

And a very crucial item before we get back on to our main agenda.

Depending upon how we write the code, the methods may be loaded in memory multiple times. Which is bad for the application. We do not want identical piece of code to be loaded in memory multiple times. The code must be loaded only once and be executed in the context of the corresponding object. What am I talking about? Update the code for the method validateUser as follows:

JavaScript
function validateUser()
{
  var eid = document.getElementById('i').value;
  var uname = document.getElementById('u').value;
  var pwd = document.getElementById('p').value;

  var ep1 = new EmployeeProfile(uname, pwd, eid);
  var ep2 = new EmployeeProfile(uname, pwd, eid);

  alert('Are references same? ' + (ep1.authenticate == ep2.authenticate));
}

You are bound to get a false! It hurts. :(

Everytime we instantiate EmployeeProfile (or even UserProfile for that matter), code for the method authenticate is loaded into memory. Imagine if we have 1000 instances. Not only are the properties loaded into memory 1000 times, but also the code for the method. It's just too bad.

Let's fix this up...

Update the code for UserProfile to as follows:

JavaScript
function UserProfile(username, password)
{
  this.username = username;
  this.password = password;
}

UserProfile.prototype.authenticate = function()
{
  if(this.username == 'gvaish' && this.password == 'edujini')
  {
    return true;
  }
  return false;
}

Notice the use of prototype property once again. That holds the key! That's probably - The Key property in JavaScript.

Now, execute the test case once again. ep1.authenticate == ep1.authenticate must return true in this case! Detailed discussion around prototype is out of the scope of this article... but will have one some time soon.

Method Overriding

Next, we explore how to override the method authenticate. Update the definition of EmployeeProfile as given below:

JavaScript
function EmployeeProfile(username, password, employeeID)
{
  this.username = username;
  this.password = password;
  this.employeeID = employeeID;
}

EmployeeProfile.prototype = new UserProfile();

EmployeeProfile.prototype.authenticate = function()
{
  if(this.employeeID == 123 && this.username == 'gvaish'
                  && this.password == 'edujini')
  {
    return true;
  }
  return false;
}

Go ahead and authenticate with various combinations of the employeeID, username and password. Hurray! The method has been overridden (using the line of hierarchy of the object prototype).

The last thing that we see in method overriding is how to invoke the base-type method in the sub-type method. Well, the solution again lies in prototype!

Let us define the business logic for an employee's authentication as follows:

  1. It checks for the authentication results from UserProfile. If it has failed, the result is failure.
  2. It additionally checks for employeeID.

This way we keep EmployeeProfile independent of how the UserProfile authenticates itself. Modify EmployeeProfile as follows:

JavaScript
function EmployeeProfile(username, password, employeeID)
{
  this.username = username;
  this.password = password;
  this.employeeID = employeeID;
}

EmployeeProfile.prototype = new UserProfile();

EmployeeProfile.prototype._authenticate = EmployeeProfile.prototype.authenticate;

EmployeeProfile.prototype.authenticate = function()
{
  if(this._authenticate())
  {
    return this.employeeID == 123;
  }
  return false;
}

Note that this is one of the various possible ways of achieving our target. We create a reference _authenticate to the original authenticate method (but did we get it from EmployeeProfile since we defined it in UserProfile - that's the magic of prototype in JavaScript).

Rerun your test case... Wow! We get what we expect...

Summary

In this article, we learnt how encapsulation is implemented in JavaScript. To summarize, we explored the following:

  • Inheritance in JavaScript
  • Use of prototype property to mark inheritance
  • Defining new methods in the inherited type
  • Override existing methods, optionally also calling the original method
  • instanceof operator to check the underlying data-type inheritance hierarchy

License

This article, along with any associated source code and files, is licensed under The BSD License