JavaScript Patterns in Object Oriented Programming and Inheritance

When I first started learning JavaScript, I would challenge myself by reading source code I would find at Github from some open-source repo. Other times, I would just view > source a website and look under the hood. This, I thought, would verify that I was indeed understanding the theory and concepts I learned from books. Often, however, these autodidactic activities resulted in my spirits crushed as I encountered code blocks that were too convoluted and elaborate; code that would use all those little building blocks of the language (logical operators, keywords, variable scope, etc) together in order to build a complex architecture I was completely ignorant of and intimidated by. In short, I would just run into code that was well beyond my limited comprehension.

One thing I did notice was that there was a lot of similarities between code blocks. Which meant there was probably a fairly standardized, conventional pattern being used.  Lately, I’ve finally got a chance to be introduced to these patterns thanks to my current university class. And so I though’t it’d be beneficial to share some of these pervasive patterns that you’ll likely find at some point in your journey as a JavaScript developer. So without further ado, let’s get to it.

Factory Pattern

The first time I heard about this pattern was on Addy Osmani’s book which covers this pattern (and so many others) much more extensively. I’m gonna show you the TLDR; version. In essence, the factory pattern is a function that creates an object and returns it so that it can be stored in a variable, or chained to other methods, etc.

Here is an example of a simple factory:

 

With this function defined, we can instantiate objects by calling the function and storing the returned object in a variable outside of the factory function scope. Then we can call the methods that are shared by all instances of the same band Object type, or all objects created with our createBand() function

 

Disadvantages

Though this pattern lets the programmer create Objects that share the same methods and properties, the objects created do not have a type other than the generic JavaScript Object object. This is not very useful in practice because if at some point we neededto know if radiohead is related to af there is no way to tell since both objects don’t belong to a distinct type, or class. They just belong to the Object type, which is very broad. Strings, Arrays, Functions, are all part of the Object type as well, so wee need to fix this ambiguity.

To define the type, we will need a constructor function.

 

 

Constructor Pattern

The constructor pattern lets us construct objects that belong to a specific type or class. In our previous example, we had no way to find out if the objects being referenced by the radiohead and af variables were similar, or had the same property fields and methods. In other words we did not know if those two objects were part of the same class.

The key in the constructor pattern is the new keyword. We define a constructor function, and then instantiate the objects defined by such function using the new keyword. Example

 

* Coding convention: All constructor function names begin with an uppercase letter i.e Band

Disadvantages

There is a couple of potential pitfalls when dealing with constructors. First, if your code invokes a constructor function without the new keyword, the properties defined for the object we defined are now applied or added to the global object, which, in the DOM’s case, is the window object. So, to illustrate what I mean:

The other obstacle that constructor functions impose, is that with each instance of an object has it’s own definition of each method. Suppose we create 100 Band Objects. All it’s well until we decide that, for some reason, we want to change the message returned by the greeting() method. In this scenario we would have to change the method 100 times! This is a maintainability nightmare, and not very efficient.

With that said, there’s a solution to this problem. Enter the famous prototype.

 

Prototypes and Inheritance patterns

This feature in JavaScript is what enables us as developers to start building classes, and objects that inherit from others. Now, prototypes were perhaps the toughest pill to swallow while learning these advanced JavaScript concepts because the concept is very, very abstract. But nonetheless I will do my best to explain them to the best of my ability.

Basically a Prototype in JavaScript is an abstract, “invisible” object (meaning you don’t really see it in your source code) from which other related objects inherit. Whenever we define a new object we are actually creating it’s prototype as well. All instances of an object created via a constructor will inherit those properties that were set in the original definition of the constructor function.

All objects in JavaScript (native or created by developers) inherit properties and methods from their respective prototypes. For example, all strings created in JavaScript have the toLowerCase() method because they inherit it from the native String Object that comes in the JavaScript core. Because of this inheritance relationship, we as programmers benefit greatly since we do not have to define a toLowerCase() function every time we want to create objects of the String type; rather all strings we create have that method available to them, at any time.

To illustrate inheritance using native objects, let’s try and access the toLowerCase() method, override it with some code, and see if all String objects experience the change:

 

Overriding native object’s methods and properties is something you don’t want to do, ever, but this example hopefully illustrates the nature of the prototype and prototypal inheritance.

Now, let us combine the modularity of constructor functions, with the efficiency of prototypal inheritance to create a Band class.

To do this, we use the constructor function to help us pass in variables unique to each object during instantiation, known as instance variables, and we use the prototype approach to define any property or method that will be the same in all instances of the object.

 

 

Inheritance with Subtypes

Sometimes we have to deal with a multi-layered hierarchy of objects in our application. So far our code has created a Band Object and instantiated Bands that shared a common prototype. But what if our application demands a more specific class hierarchy. What if we needed to create Rock bands, or Country Bands specifically? And what if we wanted them to share methods and properties of the Band type, but also have methods and properties of their own?

Luckily there’s a pattern that enables this:

 

Conclusion

The patterns I’ve presented in this post are just a few of many, many more out there. But I’d say that these are fundamental in any JavaScript developer’s formation. The ability to create, modify, and extend an object’s prototype with custom properties and methods are a core skill in web application, framework, and plugin development. Once you begin to internalize these patterns, the task is not so daunting and scary anymore., isn’t it?