Introduction to Encapsulation in JavaScript
JavaScript is a sturdy object-oriented scripting language, which is capable of building complex applications on both the client and the server. However, the higher the complexity in the implementation, the better maintainable and flexible code is needed to tackle the situation. Encapsulation, one of the principles of Object-Oriented Programming is the key to achieve such goals.
By definition Encapsulation in JavaScript is a process of binding the data with the functions which act upon the data. Encapsulation allows us to control and validate the data. In JavaScript, variables resemble data.
Encapsulation means information hiding i.e. the idea that the internal entities of an object should not be directly bare as public entities. This will help restrict the unauthorized use of the variables. Instead, if the callers want to achieve a defined result it should use the public method or public entities inside the object to access the private variables of the object.
Working of Encapsulation in JavaScript
Let’s take a simple problem where an “employee” object contains two attributes “name” attribute.
var employee = {
name : "Aditya Chaturvedi",
};
alert(employee.name); // Aditya Chaturvedi
employee.name = "Rahul Khanna";
alert(employee.name); // Rahul Khanna
Everything looks fine in the above example. We created the object, printed its attribute value and modified it. But the problem seems to arise when some user tries to set an integer value to the name attribute.
employee.name = "Amit Trivedi";
alert(employee.name); // Amit Trivedi
As far as JavaScript is concerned this is completely legal as in JavaScript a variable can accept any type given to it. In order to rectify this, we need to set the range of valid characters that can be set to the attribute name of the object. These Validations can’t work if the caller can access and modify the value of these data. The simple solution for this would be
var employee = {
name : "Aditya Chaturvedi",
setName : function (value) {
var exp = new RegExp(/\d+/);
if( exp.test(value) ) {
alert("Invalid Name");
}
else {
this.name = value;
}
},
"getName" : function() {
return this.name;
}
};
alert( employee.getName() ); // Aditya Chaturvedi
employee.setName( "Rahul Khanna" );
alert( employee.getName() ); // Rahul Khanna
employee.setName( 42 ); // Invalid Name
alert( employee.getName() ); // Rahul Khanna
The above example applies the validation but still has some faults as if the caller access the name directly, he can still change it.
employee.setName( 42 ); // Invalid Name; Here name won’t be changed.
employee.name = 42; // No validation happens and the name is changed
alert( employee.getName() ); // 42 is printed.
The end goal over here is that the variable name should not be available globally with the object “employee”. Encapsulation helps it out. This can be solved by the concepts Function Scope and Closures.
1. Function Scope
Any Variable which is written inside the code block of the functions remains hidden from outside.
function fnScope()
{
var fnVar = "Hi!";
alert( fnVar ) // "Hi!";
}
alert( fnVar ) // error; fnVar is not accessible outside the function.
Hence if we move the variable “name” inside the function “setName” then the callers won’t be able to access it directly. But this is not easy to directly put the variable “name” inside the function “setName” as the variable inside a function block can’t be used outside its scope, hence name would not be available for “getName” method. For this Closure will help.
2. Closures
When two functions are bundled together with references to their surrounding state or the lexical environment is known as a closure. In simple words, closure gives access to a local variable of a function to be used by another function inside a parent function. Here we have a variable name hiding inside the function setName from the outside world. But the inner object (myObj), can access it:
var employee = function () {
var name = "Aditya Chaturvedi";
var exp = new RegExp(/\d+/);
var myObj = {
setName : function (value) {
if( exp.test(value) ) {
alert("invalid name");
}
else {
name = value; // The object has access to "name"
}
},
getName : function () {
return name; // The object has access to "name"
}
}; // End of the Object
};
employee.getName(); // doesn't work!
Now we have used the concept of closure, the inner object myObj can be accessed by both the functions. But still, there is a fault to access the inner object. Above we have seen employee.getName can’t be used, neither employee.myObj.getName can be used since myObj is also private to the function and private variables can’t be accessed outside like this. Hence we need to return the inner object whenever the anonymous function is called and assign it to an outside variable.
var employee = function () {
var name = "Aditya Chaturvedi";
var exp = new RegExp(/\d+/);
return {
setName : function (value) {
if( exp.test(value) ) {
alert("Invalid Name");
}
else {
name = value;
}
},
getName : function () {
return name;
}
}; // end of the return
}(); // Note this '()' means we're calling the function
// and assigning the returned value to the variable employee
alert(employee.getName()); // Aditya Chaturvedi
employee.setName( "Rahul Khanna" );
alert(employee.getName()); // Rahul Khanna
employee.setName( 42 ); // Invalid Name; the name does'nt changes.
employee.name = 42; // Doesn't affect the private fullName variable.
alert(employee.getName()); // Rahul Khanna is printed again.
Advantages of Encapsulation in JavaScript
The main advantage of using encapsulation in JavaScript is to provide security to the data. Other benefits of encapsulation include:
- Encapsulation guards an object against illegal access.
- Encapsulation helps to achieve a level without revealing its complex details.
- This will reduce human errors.
- Make the application more flexible and manageable.
- Simplifies the application.
Conclusion
Encapsulation is the tool in JavaScript which can be used to make the complex operation easy and manageable with making the overall application secure and easy to work.