Introduction
One of the most battle tested and long standing languages is JavaScript. Almost any front end framework you touch today is created mostly based on JavaScript. Still, even today, we see a lot of JavaScript in many websites that is written in a Spaghetti coding style. We see so many JavaScript methods hastily put together in large files ultimately creating global namespace pollution, with no chance for code roust etc.
In this article, we will see some techniques on how we can convert a set of loosely written JavaScript methods to a more modular design that we are more accustomed to seeing in an object oriented language such as C#.
Issues with loose JavaScript methods
Before we discuss some of the design patterns, let us first understand some of the basic issues that occur when we do not go for a modular design.
Please refer the below code listing,
- var add = function (a, b) { alert(a + b); };
- add(1, 2);
In the above listing, add(1,2) alerts the value 3. Now, what happens if we declare “add” again as shown below,
Fiddle
reference This throws an error since the variable add has been overwritten. Though the problem is obvious here, it may not be always obvious when your overriding takes place in a different file and the method call happens in another file.
Basically, the problem here is that we are polluting the global namespace. Any variable we create here is added to the global scope. Our code should be written in such a manner that we
do not add any variable to the global namespace unless absolutely necessary to do so for solving a business case.
Ok, now that we are warmed up to the issues, let us see how we can solve this problem using some common JavaScript design patterns! We will discuss two common design patterns in the interest of not making this post very lengthy and basically to get developers get started in the path of understanding organizing JavaScript code in a much better manner.
Module Pattern
Module pattern is a favorite pattern for many due to it close resemblance to class and object declaration in a OOPs language such as C#.
Closure in JavaScript is the driving principle behind making the modular pattern. In case you have not heard of closures in JavaScript, it is a good idea to read up on this as this is one of the principal foundations in JavaScript. Basically, closure in JavaScript enables private (local) variables of a JavaScript function to be kept alive even after the function has returned. This is enabled when the private (local) variable is referred inside a function that is returned by the parent function. Well, closure is a complex topic which is outside the scope of this discussion, but I would strongly suggest reading and understanding closures in JavaScript to really grow into a seasoned JavaScript developer.
Ok, now let us look at an example of a module pattern implementation and then discuss its anatomy and learn about it.
Let us say we have the following listing which is basically just a set of loosely defined methods to implement addition and subtraction. We convert it to use a modular pattern as shown below.
JSFiddle
reference.
- var add = function (a, b) {
- alert(a + b);
- };
- var subtract = function (a, b) {
- alert(a - b);
- }
- add(1, 2);
- subtract(4, 2);
In the above listing we are declaring two variables, add and subtract. Thus, we are polluting the global namespace and also we are opening ourselves to the situation where another file can overwrite these variables add and subtract with a different implementation or worse, convert it to a simple variable holding just an integer or string!
-
- var Calculator = function () {
-
- var addition = function (a, b) {
- alert(a + b);
- };
- var subtraction = function (a, b) {
- alert(a - b);
- }
- return {
- add: addition,
- subtract: subtraction,
- multiple: function (a, b) {
- alert(a * b);
- }
- }
- };
-
- var calculator = new Calculator();
- calculator.add(1, 2);
- calculator.subtract(5, 1);
- calculator.multiple(2, 4);
Please note the above listing. See how we have taken the addition and subtraction method and converted it as private variables (you can test it, by trying to execute calculator.addition(1,2), it will throw an error).
In the public API for this function, we only return three variables, add, subtract and multiply, which can be called by an instance of Calculator.
Another good practice to follow is whenever you are declaring a class (a function) which will need to be initialized using a new operator to create objects, it is a standard practice to use Pascal casing (as we follow in C#). This is because, in JavaScript, the usual practice of variable naming is to use camel casing.
Also note, how we have only created one global variable in this case. You can reduce it still further by reusing an existing namespace. You can do something as follows,
var ns = ns || {} The above lines mean, if the namespace variable ns exists, then use it, else create an empty object. Thus no danger of overwriting existing namespace/variable with your definition.
The only major disadvantage with modular pattern is that for each instance you create, you get the functions loaded in memory. Well, unless you are creating hundreds of objects, this may not actually prove to be an issue.
The above is an example of modular pattern. Let us now look at some other patterns.
The Prototype Pattern (“this” pattern)
The prototype pattern is another popular pattern that you can use for structuring your JavaScript code. The prototype pattern only creates one copy of the functions in memory even if you have hundreds of instances, all the instances share the same functions in memory.
The prototype pattern works on the basis of the native prototypical inheritance support in JavaScript. Basically, what we need to understand is that for any function that we create and assign to a variable, a “prototype” object is created to which you can add further methods (your API methods), that will be inherited to any object you create based on the original class (the variable which points to the function).
This pattern is also called as “this pattern” due to the heavy usage of the “this” keyword. This is the only major “disadvantage” of this pattern since the “this” keyword in JavaScript is slightly more complicated than that of other languages such as C# that we are accustomed to. The “this” keyword in JavaScript refers to the context of the caller rather than the context in which the “this” keyword is used.
Well, that was some pretty heavy stuff, let us now see some code in action. Please refer to the following listing, which is basically the same Calculator example that we used in the prototype pattern, but converted to use the Prototype pattern,
JSFiddle
location.
-
-
-
- var Calculator = function (a, b) {
- this.operand1 = a;
- this.operand2 = b;
- };
-
- Calculator.prototype = {
- add: function () {
- alert(this.operand1 + this.operand2);
- },
- subtract: function () {
- alert(this.operand1 - this.operand2);
- }
- }
- var calci = new Calculator(5, 2);
- calci.add();
- calci.subtract();
-
- Calculator.prototype.add = function () {
- alert(this.operand1 + this.operand2 + 55);
- }
- calci.add();
If you observe the output of the last line, the overridden method is called, this gives us a tremendous advantage if we want to override methods that are provided by a library. So, when you are writing a library for others to use, it is a good option to use Prototype pattern as it gives developers an easy way to override your methods without having to update your code that was downloaded as part of the library and risk having it changed when you release a new version of the library.
Well, I hope you enjoyed reading up on these two common JavaScript design patterns that you can use to convert your project code into beautiful modules!