Nowadays, Javascript is one of the most trending languages in software development. Javascript itself can be used in so many fields: from Frontend to Backend as well as from Web development to Mobile application development and even Desktop app or embedded devices. Right from its creation and several upgrades, Javascript is extremely flexible and open language. Because of that, there comes pros and cons while using Javascript. Today, I will introduce to you several patterns that are commonly be used to overcome those “cons”.
But why do we need to learn those things? Many developers claim that they just write it and it works well and returns the correct result, that’s all done. I am so sorry to say no (L), your product is getting changed so frequently. It’s not the game called “Write One, Run Forever”. Your colleagues or even you will have to dive into your code, changing something to adapt to the new requirements. Think about that case when you find your code like a mess of meaningless things and it takes hours to understand. That’s the reason why.
Before diving into patterns and snippets, I would like to explain to you some basic/advanced concepts you may have already known.
1. Basic/advanced concepts
A closure in Javascript is the ability of a function to manipulate its lexical scope (where it is defined) even when it got called in somewhere else outside its lexical scope.
There are two things to remember is that, one is that the closure of a function is created when it is defined, not when it is executed. The other is, the closure remembers the variables in its scope by reference, not by value. So when the value got changed, it will be reflected inside the function.
- IIFE (Immediately Invoked Function Expression)
As mentioned in Mozilla docs:
IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined.
It is a design pattern which is also known as Self-Executing Anonymous Function and contains two major parts. The first is the anonymous function with lexical scope enclosed within the Grouping Operator (). This prevents accessing variables within the IIFE idiom as well as polluting the global scope.
The second part is creating the immediately executing function expression (), through which the JavaScript engine will directly interpret the function.
Using IIFE, we can create a separated execution context to not overwhelming the global context. I will talk about this later.
In Javascript, except primitive types, everything else is an object including function. A callback (as known as callback function), is a function that is passed to another function as a normal object argument.
Let’s look at this code snippet:
var a = 1;
log(a + ” “+ b + ” ” + c);
var b = 2;
var c = 3;
In many languages, this will causes errors since b and c are not declared when it got used, but not Javascript as I mentioned before about its flexibility. This will output “1 undefined undefined”. And in this case, it is called hoisting. Let me explain what above code got translated using hoisting:
var a = 1;
var b;
var c;
log(a + ” “+ b + ” ” + c);
b = 2;
c = 3;
Hoisting means, all declarations (including variable and function) will be hoisted to the top of the code before any manipulation, but all the assignments are left where they are (as the above translated code with b and c).
Currying is the process of transforming a function to another function with pre-defined parameters. Let’s look at this code snippet:
var multiply = function(a, b) {
return a * b;
}
var square = function(a) {
return multiply(a, a);
}
Someone may say: “I can use bind with the first argument to be null to achieve currying?”. Yes, technically, you can. But bind is not intended to use this way. This will lead to wtf code in your program. Your colleague or maybe yourself after 1 month will ask: “What is this shit?”.
Firstly, I want to that it’s memoization, not memorization (I used to be confused when I first approached it).
Memoization is the process of caching the result of expensive operations and use it later. Think of this classic Fibonacci problem:
The Fibonacci sequence is a series of numbers where a number is found by adding up the two numbers before it. Starting with 0 and 1, the sequence goes 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, and so forth. Written as a rule, the expression is xn = xn-1 + xn-2.
In this example, xn = xn-1 + xn-2, it means xn-1 = xn-2 + xn-3, you can see the repeat of xn-2 and it can be so expensive operation on its chain, and caching it using memoization reduces the execution time quite a lot. You can find out more about how memoization is implemented, refer my Github repository here.
That’s quite enough for those boring (but important) basic concepts, now let’s dive into something more interesting.
2. Module Pattern
I am a fan of this pattern, I use it almost every time I work with Javascript. By using this pattern, your Javascript code will be organized and encapsulated. This is how it looks like:
var ModuleName = (function() {
// Your code.
})();
By using IIFE, we create a new execution context for our code to keep the privacy and reveals what we intended to public to global context. In detail, what is used inside the anonymous function will be private to global context and what is returned from the IIFE call is public to global context. That’s how your Javascript code got organized (into a specific module) and encapsulated (using the privacy).
Let’s move to detail of its implementation.
2.1. Private methods and properties
This pattern make use of the privacy of execution context to hide the private methods. Look at the below example:
// Authentication module is pre-defined under name: authenticationModule.
varCarEngineOperatorModule = (function(authenticationModule) {
// ============================================================
// Other parts of the code.
// ============================================================
var _ran_Distance_km = 1824250;
var _isAuthenticated = function(userKey) {
returnisAuthenticated(userKey);
};
var_fillFuel = function() {
// Filling fuel operations.
};
varstartCarSystem = function(userKey) {
if !_isAuthenticated(userKey) return;
_fillFuel();
// Other operations.
};
vargetRanDistance_km = function() {
if !_isAuthenticated(userKey) return;
return_ran_Distance_km;
}
// ==============================================================
// Other parts of the code.
// ==============================================================
return {
startCarSystem: startCarSystem,
getRanDistance_km: getRanDistance_km
// Other public methods.
};
})(authenticationModule);
In this example, I illustrate the processes of a self-driving car, under voice commands of the car owner.
To start the car, the user says to the car: “Okay car!” (Like “Okay Google!”). The voice command receiving module will hear the command, filter it and communicate with the car engine operator module (CarEngineOperatorModule) to start the car. In this case, the start method of the operator module (startCarSystem()) will be public to the global context, left behind operations private.
If some module attempts to call the private methods, for example _fillFuel(), there will be an error. This error is an intended action because we don’t want any module to manipulate a dangerous method out of our control (like __fillFuel()).
The similar concept is applied to private properties. We will hide some properties that only be used inside the module or can only be got under some circumstances. In this case, the number of how many kilometers the car was ran is a personal information, and we don’t like anyone to read it easily, so this information will be hidden to the outside world. After the successful authentication, you can get some information about the owner.
3. Object chain
I often use this pattern to store settings or constants in a separate area to get things organized. Once you make any change to a setting or constant or whatever you define, you will find it easy to locate the place you need to change, and change only once. You will not have to care about other positions may using your settings. This pattern uses object literal syntax by multiple layers. This is how it looks like:
varthemes = {
water: "Water",
forest: "Forest",
ocean: "Blue Ocean"
};
varsupporters = {
male: "Male",
female: "Female"
}
varconstants = {
setting: {
debugMode: false,
theme: themes.ocean,
supporter: supporters.female
},
message: {
error: {
failRequest: "Request failed! Try again later.",
authenticationFail: "You're not authenticated, not able to access this area!"
},
warning: {
delete: "You're deleting {1}. This process cannot be undone!",
grantPermission: "You're granting {1} permission to the user named {2}"
}
}
}
This pattern takes advantage of the suggestion feature of IDEs. When you type “constants.”, a list of constants will be shown for you to quickly choose the one that you need.
4. Facade pattern
If you’re working with Javascript, you will surely use libraries out there. Most of the times, we just use part of the library.
To focus on what you work with and simplify the usage of the library. Think of it as how API to other developers is implemented. It provides the simplicity to who uses it and hide the underlying complexity. Only facades are public to the outside world.
Let’s take a look at this pattern in action.
This is what I use in a real project (Take a look at this repository)
varauthFacade = (function() {
var _totp = newTOTP({
issuer: 'ACME',
label: 'AzureDiamond',
algorithm: 'SHA1',
digits: 6,
period: 30
});
return {
get2FAToken: function(callback) {
getSecretCode(function(secretCode) {
if (!secretCode) return;
secret = OTPAuth.Secret.fromB32(secretCode);
callback(_totp.generate());
});
}
}
})();
This authFacade module simplifies the OTPAuth library, by providing the get2FAToken facade, who use it just pass the callback function to work with it.
get2FAToke(callback);
The rest of the work is hidden.
Those are the most common patterns in my opinion. Hope that it helps you in your future Javascript development work.