Class and inheritance in common JavaScript

Even without the new ES6 standard, it is already possible to declare JavaScript classes with constructor and inherit from another classe.

All this is done by declaring an object - thus a function in JavaScript - differently with a closure, in other words returning a function instead of a value.

The model of declaration is offered by TypeScript. When a Car class with a speed attribute, and a constructor are declared, it generates the following code:

var Car = (function () {
  function Car(s) {
    this.speed = s;
  }
  return Car;
})();

The inner Car function is the constructor, it is the return value and therefore is called when an instance of Car is created. We check that it works by displaying the value of the speed attribute:

var myCar = new Car(150)
document.write(myCar.speed);

Adding methods

With this model of declaration, defining a method is a bit more complicated. It is declared as attribute of the prototype attribute, that every object has by default.
For example, we want to assign the autonomy of the car with the setAuto method:

var Car = (function () {
  function Car(s) {
    this.speed = s
  }
  Car.prototype.setAuto = function (d) {
    this.autonomy = d
  };		
  return Car
})();

As earlier, we verify that it works with a call to the method followed by the display of the attribute.

myCar.setAuto(1000)
document.write(myCar.autonomy)

Adding attributes

In principle, attributes are declared in the constructor. If you want to specify the name of the vehicle by the name attribute, the constructor will have this form:

function Car(s) {
  this.speed = s
  this.name="Model x"
}

It is unnecessary to declare the attribute at class level. We verify that the attribute is well recognized:

document.write(myCar.name)

Inheritance

To realize the inheritance, we resume the code used by typescript which defines a function extends.

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

We define a class Vehicle whic has a color attribute that you want to inherit:

var Vehicle =  (function () {
  function Vehicle(c) {
      this.color = c
  }
  return Vehicle;
})();

We must now add the super class at the same time as the Car class you declare. To this we must add the call to __extends and in the constructor, a call to the constructor of the super class. The name of the super class is also added at the end:

var Car = (function (_super) {
   __extends(Car, _super);

   function Car(s) {
     _super.call(this, "red");
     this.speed = s;
     this.name="Modèle x"
   }

   Car.prototype.setAuto = function (d) {
     this.autonomy = d;
   };		

   return Car;
})(Vehicle);

The _super word is not part of the language, but is invented to pass attributes to the super class.

Now we will verify that inheritance works by referring to the color attribute that belongs to Vehicle and not Car, from an instance of Car.

document.write(myCar.color)

Multiple instances

Remains to verify that the attributes of each instance have their own values.

We see in the example below the speed assigned to v2 instance does not affect that of v1, it is the right behavior.

var v1 = new Car(120)
var v2 = new Car(240)
document.write("v1.speed=" + v1.speed)
document.write("v2.speed=" + v2.speed)

Static attribute

To declare a static attribute, it is simply declared in the class with the class name:

Car.fuel = 4

It is then possible to access the attribute directly with the name of the class, but as is also the case with PHP it is not possible to access it in an instance.

Car.fuel = 5
var v3 = new Car(150)
document.write("Car.fuel=" + Car.fuel)
document.write("v3.fuel=" + v3.fuel)

The value of fuel is undefined for the instance, which is normal behavior.

Conclusion

These JavaScript pseudo-classes can do all that is expected of a class, and are equivalent to PHP classes. They have a small functional defect that you lose the ability to declare a private attribute. And also a praxtical default that the declaration of inheritance is not very readable.
If you want to use inheritance extensively, it will be easier to use TypeScript to produce the JS code from a much simpler source code.
This pending ECMAScript 6 is implemented on all browsers on which you want to run your application, and then provide us with classes and inheritance in a simple and common code.

© July 21, 2014 Xul.fr