JavaScript - Encapsulation




JavaScript - Encapsulation

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.

Examples of JavaScript Encapsulation

Here is an example of encapsulation that contains two data members with its setter and getter methods -

<script>  
class Student  
  {  
    constructor()  
    {  
       var name;  
       var marks;  
    }  
        getName()  
        {  
          return this.name;  
        }  
      setName(name)  
      {  
        this.name=name;  
      }  
        
      getMarks()  
      {  
        return this.marks;  
      }  
    setMarks(marks)  
    {  
      this.marks=marks;  
    }  
  
    }  
    var stud=new Student();  
     stud.setName("raja");  
     stud.setMarks(90);  
     document.writeln(stud.getName()+" "+stud.getMarks());  
</script> 

Output

Raj 90

Encapsulation is one of the main concepts in object oriented programming. It allows an object to group both private and public members under a single name. All the object oriented programming languages support this. Since JavaScript is also an object oriented programming language, it supports it too. In this article, we will see how to achieve encapsulation in JavaScript by creating a simple object named CssManager that helps to dynamically add, remove, or swap a style-sheet.

Encapsulation is one of the fundamentals of OOP (object-oriented programming). It refers to the bundling of data with the methods that operate on that data. Encapsulation is used to hide the values or state of a structured data object inside a class, preventing unauthorized parties’ direct access to them. Publicly accessible methods are generally provided in the class (so-called getters and setters) to access the values, and other client classes call these methods to retrieve and modify the values within the object.

The most important principle of object orientation is encapsulation: the idea that data inside the object should only be accessed through a public interface – that is, the object’s methods. If we want to use the data stored in an object to perform an action or calculate a derived value, we define a method associated with the object which does this. Then whenever we want to perform this action we call the method on the object. We consider it bad practice to retrieve the information from inside the object and write separate code to perform the action outside of the object.

What is an JavaScript Encapsulation ?

I recently had a discussion with a colleague about encapsulation. We lamented the fact that many developers cannot adequately define, describe or otherwise communicate the concept during the interview process – even at the “senior developer” level. After our conversation, I went home and Googled “JavaScript encapsulation” just to see what came up. After seeing the search results I am not at all surprised that few JavaScript programmers really understand the concept. I didn’t feel satisfied by any of the examples or definitions I found, so here’s my crack at explaining things.

While this is no longer late breaking news, it bears repeating: JavaScript is a powerful object oriented language, capable of being used to build sophisticated applications on both the client and the server. However, the more sophisticated the implementation, the bigger our responsibility to create maintainable and flexible code. In this article, I demonstrate how to use one of the pillars of object oriented programming, “encapsulation,” to help achieve these goals.

Encapsulation includes the idea that the data of an object should not be directly exposed. Instead, callers that want to achieve a given result are coaxed into proper usage by invoking methods (rather than accessing the data directly).

Let’s take a simple example where a “person” object contains a “fullName” attribute.

var person = {
  fullName : "Jason Shapiro",
};
 
alert(person.fullName); // Jason Shapiro
person.fullName = "Jim White";
alert(person.fullName); // Jim White

Everything looks OK, so far. We created the object, printed and changed the fullName without any issues. However, imagine that someone accidentally misuses this object, and sets the fullName to an invalid value, such as a number −

person.fullName = 42;
alert(person.fullName); // 42

This is perfectly legal. As far as JavaScript is concerned, a variable can accept any type of data as its value. However, we may want to restrict the range of valid characters to satisfy how we use the fullName in our application. If we allow the caller to access and modify the data directly, we can’t force any validation logic to take place when they set the value.

Furthermore, we may want to change how we store and/or construct the fullName value. Perhaps, at a later date, we decide that we want to break up the fullName variable into two separate variables: “firstName” and “lastName.” Again, allowing the caller direct access to the data is problematic: we can’t modify the internal data structure without breaking their accessor calls.

An Incomplete Solution

Let’s tackle the first issue (data validation) by modifying the object to contain a setFullName method. The goal of this method is to ensure no numeric characters are included when the name is set by the caller.

 var person = {
 fullName : "Jason Shapiro",
  setFullName : function (newValue) {
    var reg = new RegExp(/\d+/);
    if( reg.test(newValue) ) {
      alert("Invalid Name");
    }
    else {
      this.fullName = newValue;
    }
  },
  "getFullName" : function() {
    return this.fullName;
  }
};
 
alert( person.getFullName() );   // Jason Shapiro
person.setFullName( "Jim White" );
alert( person.getFullName() );   // Jim White
person.setFullName( 42 );        // Invalid Name
alert( person.getFullName() );   // Jim White

Looks better. When the caller calls “setFullName” it ensures the name doesn’t contain a digit. But unfortunately, we’re only half way there. This strategy requires a wink and a nod from the caller ensuring that they promise not to call “fullName” directly. The code as written, however, won’t stop them from breaking this informal contract −

person.setFullName( 42 ); // Invalid Name; the name is not changed.
person.fullName = 42;     // No validation is executed; the name is changed and...
alert( person.getFullName() );   // ...42 is printed

The end goal here is to prevent callers from accessing fullName directly, which is where encapsulation comes into the picture. In order to hide our fullName data, we’ll need to learn two new concepts: function scope and closures.

Function Scope

Variables declared in a function are hidden from any code outside of its definition.

function scopeTest()
{
   var functionVariable = "Hello!";
   alert( functionVariable ) // "Hello!";
}
 
alert( functionVariable ) // error; functionVariable is not available outside of the function.

Therefore if we move the fullName variable inside of a function/method, callers won’t be able to invoke it directly. However, we can’t simply move the variable to the inside of the “setFullName” method; methods of an object can’t see each other’s local variables! In other words, if fullName was added to setFullName, it would not be available to any another method, such as getFullName. This is where closures help us out.

What is Encapsulation?

Encapsulation is a term that applies to any programming language (although this discussion will relate specifically to JavaScript). The basic idea is to restrict access to certain data structures by defining these elements as public, protected, or private. Another way to describe encapsulation is to “build a protective capsule” around some data structure. Encapsulation is pretty straight-forward, but it is “easier” to implement in some languages. For example, Java allows us to use the “public” and “private” modifiers to describe properties -

Public class Person {
    public String name;
    public int age;

    private String SSN;

...
}

Because JavaScript is not your typical “classical OOP” language, we don’t have the ability to explicitly mark some object properties as “private”… we have to rely on other structures within JavaScript, namely the closure, to achieve this.