Class and inheritance simulation techniques in Javascript (ECMAScript)

View more Tutorials:

1- Class in Javascript

Javascript means in fact a world of functions and objects. It is originally designed simply, with no clear concept of classes. Perhaps, the Javascript creators cannot think that one day this language is used so widely. 
The object in Javascript means an entity with multiple " Key/Value" pairs, and you can access values via objects and keys. 
object-example1.js
var tom =  {
  name: "Tom",
  country: "American"
};

// Access:
console.log( tom.name ); // Tom
console.log( tom.country ); // American
console.log( tom["name"] ); // Tom
console.log( tom["country"] ); // American

 
You can add new  "Key/Value" pairs to an available object or remove its "Key/Value" pairs  
object-example2.js
var tom =  {
  name: "Tom",
  country: "American"
};

// Delete property - country
delete tom["country"]; // Same as: delete tom.country;

// Add property - gender
tom["gender"] = "Male"; // Same as: tom.gender = "Male";


// Access:
console.log( tom.name ); // Tom
console.log( tom["name"] ); // Tom

console.log( tom["country"] ); // undefined
console.log( tom.country ); // undefined

console.log( tom["gender"] ); // Male
console.log( tom.gender ); // Male
Class is a modern concept in the languages such as Java, C #, ... Class is a design. Using this design helps you quickly create objects with the same structure. The first version of Javascript does not have this concept. 
Javascript is more and more  important so it needs to be upgraded. Javascript designers try to simulate the concept of Class based on the concepts available in Javascript. The syntax for simulating a class is introduced in ES3, ES5, but not until ES6, we have a modern syntax, and which satisfies everyone. 
First of all, for simplification, see a modern syntax introduced in ECMAScript 6 to create the Rectangle class, with 2 properties such as width and height .  This class has a getArea() method that returns the area of this rectangle. 
es6-class-example.js
// ECMAScript 6 class:

class Rectangle  {

  constructor (width , height)  {
      this.width = width;
      this.height = height;
  }

  getArea()  {
    return this.width * this.height;
  }

}


// ------------- TEST -------------------

var rect = new Rectangle(10, 5);

var area = rect.getArea();

console.log("Width: " + rect.width);
console.log("Height: " + rect.height);
console.log("Area: " + area);

 
Creating a subclass of a class is very simple with  ES6:
es6-inheritance-example.js
class Shape  {

    constructor( x, y) {
        this.setLocation(x, y);
    }

    setLocation(x, y) {
        this.x = x;
        this.y = y;
    }
}

// Subclass:
class Circle extends Shape {

    constructor(x, y, radius) {
        // Call Shape's constructor via super
        super(x, y);
        this.radius = radius;
    }

    getArea() {
      return Math.PI * this.radius * this.radius;
    }
}

// ----- TEST ----


var circle = new Circle(0, 2, 5);

console.log( circle.getArea() );

 
ES6 introduces a modern syntax for creating a class, and subclasses, but the technique really doesn't change. The  ES6's syntax obscures the confusing concepts of Javascript when it tries to simulate a class. In this lesson, I discuss with you how ES3 & ES5 did to simulate a class and inheritance. 

2- Class and inheritance in ES3

ES3 uses the  function keyword to define a  "object constructor". You will create a new object when you call this function with the new operator:  
// ECMAScript 3 class.

function Rectangle(width, height)  {
   this.width = width;
   this.height = height;
}

// Create an Object:
var rect = new Rectangle(10, 5);
 
The following figure illustrates the action performed by the Javascript executing machine: 
  1. The 'rect' object is created (it's just a normal object. Nothing is special)
  2. Add property __proto__ for the 'rect' object. This is a hidden property.
  3. This variable will be pointed to the address of the 'rect' object.  
  4. Add the width property to the "rect' object.
  5. Add the height property for 'rect' object.
Prototype concepts are also introduced in ES3. Let's see what is its purpose? 
// ECMAScript 3 class.

function Rectangle(width, height)  {
   this.width = width;
   this.height = height;
}

Rectangle.prototype.bgColor = "red";
Rectangle.prototype.borderColor = "blue";

// Create an Object:
var rect = new Rectangle(10, 5);



console.log(rect); // Rectangle { width: 10, height: 5 }
console.log(rect.__proto__); // Rectangle { bgColor: 'red',borderColor: 'blue' }

console.log(rect.__proto__.bgColor); // red
console.log(rect.__proto__.borderColor); // blue

// (Read the explanation**)
console.log(rect.bgColor); // red
console.log(rect.borderColor); // blue

 
What happens when the JavaScript runtime encounters the myObject.myProperty expression? 
  • The answer is that it will check if the myObject object has myProperty property or not. If any, it accesses to this property, vice versa it accesses myObject.__proto__.myProperty.
es3-proto-example3.js
var rect =  {
   __proto__ : { bgColor : "red", borderColor : "blue" },
   width: 10,
   height: 5
}


console.log(rect.width); // 10

console.log(rect.__proto__.bgColor); // red


console.log(rect.bgColor); // red

 

new AFunction(args) vs AFunction.call(anObj, args)

Inheritance

For  ES3, you can simulate a class that inherits another class in many different ways, certainly, it's not as easy as you do in ES6, and it's quite confusing for many programmers. 
For simplicity, I give an example of inheritance, and analyze the operating rule of the Javascript runtime  n this case.
  1. The Animal class has the 2 name & gender properties.
  2. The Cat class inherits from the Animal class. It has 1 color property.
es3-inheritance-example1.js
function Animal(n, g) {
    this.name = n;
    this.gender = g;
}


function Cat(n, g, c) {
    Animal.call(this, n, g);
    this.color = c;
}


var tom = new Cat("Male", "Tom", "Black");

// Cat { gender: 'Male', name: 'Tom', color: 'Black' }
console.log(tom);

Inheritance and role of prototype (ES3)

es3-inheritance-example2.js

// Class: Animal
function Animal(n, g) {
    this.name = n;
    this.gender = g;
}

Animal.prototype.sleep = function()  {
    console.log("Animal sleeping..");
}

Animal.prototype.move = function()  {
    console.log("Animal moving..");
}

// Class: Cat
function Cat(n, g, c) {
    Animal.call(this, n, g); // IMPORTANT!!
    this.color = c;
}

// IMPORTANT!!
var TempFunc = function() {}; // Temporary class.
TempFunc.prototype = Animal.prototype;
Cat.prototype = new TempFunc();
// ------------------


Cat.prototype.cry = function()  {
    console.log("Meo meo");
}

// Override 'move' method of Animal.
Cat.prototype.move = function() {
    console.log("Cat moving..");
}

var tom = new Cat("Male", "Tom", "Black");

// Cat { gender: 'Male', name: 'Tom', color: 'Black' }
console.log(tom);

tom.move(); // Cat moving..
tom.sleep(); // Animal sleeping..
tom.cry(); // Meo meo
 

3- Class and Inheritance in ES5

Object.create(srcObject)

The  Object.create(srcObject) method creates a new  newObject object, in which  newObject.__proto__ is copy of  srcObject.
method-object-create-example.js
var john = {
  name: "John",
  gender: "Male"
};

var other = Object.create(john);


console.log(other.__proto__); // { name: 'John', gender: 'Male' }
 

Inheritance (ES3 + Object.create)

Using the Object.create(srcObject) method of  ES5 helps you simulate class and inheritance more easily than ES3
es5-inheritance-example1.js
// Class: Animal
function Animal(n, g) {
    this.name = n;
    this.gender = g;
}

Animal.prototype.sleep = function()  {
    console.log("Animal sleeping..");
}

Animal.prototype.move = function()  {
    console.log("Animal moving..");
}

// Class: Cat
function Cat(n, g, c) {
    Animal.call(this, n, g); // IMPORTANT!!
    this.color = c;
}

Cat.prototype = Object.create(Animal.prototype); // IMPORTANT!!

Cat.prototype.cry = function()  {
    console.log("Meo meo");
}

// Override 'move' method of Animal.
Cat.prototype.move = function() {
    console.log("Cat moving..");
}

var tom = new Cat("Male", "Tom", "Black");

// Cat { gender: 'Male', name: 'Tom', color: 'Black' }
console.log(tom);

tom.move(); // Cat moving..
tom.sleep(); // Animal sleeping..
tom.cry(); // Meo meo

View more Tutorials: