Click here to Skip to main content
15,867,851 members
Articles / Programming Languages / Javascript

Exploring OOPS - JavaScript Style: Part 2 - Inheritance

Rate me:
Please Sign up or sign in to vote.
3.09/5 (8 votes)
2 Aug 2008BSD5 min read 29K   88   12   1
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


Written By
Architect
United States United States

Gaurav lives in Silicon Valley.


His technical strength lies in having deep understanding of not one or two but bunch of enterprise frameworks.


Lately, he is working on an MVC framework implementation for Android put in open domain at http://sf.net/projects/android-mvc


Today, he is an independent guy:


  • He is a programming language independent guy, well almost. He is proficient in C, C++, Java, C#, VB.Net, C++.Net, JavaScript, PHP, Tcl, Python, Ruby
  • He is an OS independent guy, well almost. Has worked and developed at length on HP-UX, Linux (Redhat / Mandrake), Macintosh (9, 10.x), Windows (NT, 2000, 2003, XP, Vista), Solaris (8, 9, 10); and mobile platforms Android, iPhone, Blackberry
  • He is a target independent guy, well almost. Has worked on thick clients (mainly desktops) as well as thin clients (mainly alternative platforms - Symbian, PalmOS, WinCE, WinXP Embedded, Linux Embedded, Android, iPhone, Blackberry)



Today, his thrust areas are Service Oriented Architecture (implementation expert in Java, .Net and PHP; integration with Mainframe and other legacy environments), Mobile Technologies and RFID.



He holds a Bachelor's Degree (B. Tech.) from IIT Kanpur www.iitk.ac.in. His major was in EE with specialization in DSP (SSP).



His hobby is listening music, reading books (no, he can't read novels), photography and travelling.



Should you wish to talk to him, you can drop him a mail at gaurav[dot]vaish[at]gmail[dot]com. He generally responds within 24-48 hrs unless there is a compelling reason.



And yeah... here's his personal website:
http://www.m10v.com



Smile | :)


Comments and Discussions

 
GeneralMy vote of 5 Pin
chandan123566-Mar-13 2:49
chandan123566-Mar-13 2:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.