Pseudoclassical Pattern in JavaScript

I am sure many of you wouldn't have heard of this term Pseudoclassical, it sounds too complicated but its just a pattern in which you can implement classes in your JavaScript code.

Tutorials out there are about Classes and Prototype in JavaScript show mostly bad implementations of these conceptss, even on some of the reputed sites. And for a begginner it all gets too complicated when prototype chain and constructor's come into picture.

In this post, we will see the psuedo-classical way of implementing Classes and Inheritence in JavaScript.

Befor proceeding, i assume you are familiar with Scope's and Execution Context and how this works in javascript.


To understand psuedoclassical pattern, we must first look at the functional pattern of defining Classes.

Functional Pattern for defining a class

Code:

function Building(latitude, longitude){
    var obj = {};
    obj.latitude = latitude;
    obj.longitude = longitude;
    return obj;
}

var building = Building(77.89, 89.77);

Lets add a getAddress() method to the Building class in the above example

>First way of doing it would be add the method in the class itself

function Building(latitude, longitude){
    var obj = {};
    obj.latitude = latitude;
    obj.longitude = longitude;
    obj.getAddress = function(){
        //Some code
        return address;
    }
    return obj;
}

The above way of adding a method to a class is bad, as it will always create a new instance of getAddress method whenever a new object is instantiated by the Building class.

Prototype to the rescue

> Second way we can add a method 
function Building(latitude, longitude){
  var obj = Object.create(Building.methods);      
  obj.latitude = latitude;
  obj.longitude = longitude;      
  return obj;
}

Building.methods = {
    getAddress: function(){};
    //Other methods
};

What this line var obj = Object.create(Building.methods); would do is, bind our new obj to delegate property lookups to the Building.methods object.

To make the code more understandable, one way is to completely replace the Building.methods object and add methods directly to the Building.prototype container object as below.

Building.prototype.getAddress = function(){};

//Change the line in Building Class

var obj = Object.create(Building.prototype);

Now whenever building.getAddress() is called, it will lookup for the property getAddress which is not present in the object itself, so it will delegate the lookup to its prototype which has the getAddress method as we instantiated the obj's prototype with Building.methods using Object.create.

Note: the prototype object has a very special constructor property, which is nothing but the Class itself.

In above example,

 Building.prototype.constructor is Building itself.

Just in case you are not aware of the constructor property and are thinking what is so special about it, then you should know any objects instantiated by the Building class will have its constructor property as Building. This helps in identifying the origin of the object i.e., from the class it has been instantiated.


Pseudoclassical Pattern for defining a Classes and Sub-Classes

Suprisingly many of us already use the psuedoclassical pattern for defining classes.

Code:

function Building(latitude, longitude) {
    this.latitude = latitude;
    this.longitude = longitude;
}

var building = new Building(77.89, 89.77);

Whats different in the above code when compared to the functional class pattern is the new keyword. When we use the new keyword before the function, it runs in a special constructor mode which does most of the manual work we were doing in the functional class pattern automatically.

We can add any method we want to the Building class by adding it to its prototype object just as we did in the previous case.

Building.prototype.getAddress = function(){};

The above function will be available to all the objects instantiated by the Building class.

var building = new Building(78.89, 89.78);
building.getAddress();   //This will be found in the Building's prototype object due to delgation as we discussed above.

console.log(building.constructor) //Will log Building class
console.log(building instance of Building) //Will log true

The psuedoclassical pattern for defining a class is just a syntactical layer provided by the language.

Lets see how can we create a subclass of Building, for example we will create Home as a subclass.

We will be using .call method in our implementation, if you don't know how .call works, please check this documentation.

function Home(latitude, longitude, owner) {
    Building.call(this, latitude, longitude);
    this.owner = owner;
}

At this point, we have allowed the subclass Home objects to have the properties defined inside its superclass Building by calling it using call method.

Will the Home class objects have access to the getAddress method of Building superclass as of now?

The answer is NO

Because the getAddress method is defined in the Building's prototype and subclass Home isn't connected to it in any way.

So what should we do next, this is where most people go wrong. Our goal here is to setup something that allows the failed lookups of Home.prototype to delegate to Building.prototype.

The most common solution people propose for acheiveing the above goal is to do the below assignment:

Home.prototype = Building.prototype //Wrong as Home.prototype will point to the same object in memory as Building.prototype.

Second wrong way of acheiving the above goal is as below:

 Home.prototype = new Building(); //Wrong

 //This approach has some problems, as for every new object of subclass Home, the Building constructor will be invoked. Secondly, we won't be able to pass in any parameters to the superclass constructor as we won't know what to pass. Thus resulting in undefined being bound to the superclass properties.

So whats the best way of doing this, lets see in the code below:

Home.prototype = Object.create(Building.prototype);

Above is the correct way to acheive the above goal without any adverse effects, as Object.create will bind the failed lookup delegation from Home.prototype to the Building.prototype.

Now lets create an object of subclass Home,

var myHome = new Home(89.78, 87.98, 'Suroor Wijdan');
myHome.getAddress(); 

//subclass object will have access to superclass method due to failed lookup delegation being linked up.

We have forgot one really important thing here before this superclass and subclass is complete, any guesses?

Lets dry run a simple line of code

console.log(myHome instance of Home) //This will log false 

Confused?, As you can see we have overridden the sub-class prototype object with Object.create, the original constructor property of Home.prototype is lost and when we run an instanceof check, Home is no where to be found in the myHome's prototype chain. Thus resulting in false.

So now we need to add the original consturctor back to the subclass prototype object.

Home.prototype.constructor = Home;

Lets see all the code at once in this gist:

That's it, this is all about Pseudoclassical pattern in JavaScript. If you have any questions or find any improvement to the information above, please feel free to drop a comment.

comments powered by Disqus