Javascript OOP- protect your object data with encapsulation
By: Dusing Chang
Tags: Object Oriented, Backend Development, Computer Science, JavaScript, Front End Development

The very first step to building up an OOP project is to encapsulate it. This significant step is about setting a boundary for accessing data. without the restriction of access, mutable variables will cause race condition, which leads to unpredictable consequences and bugs.

People may think that why not just give unique names for everything in our project. It sounds reasonable. But if the project is huge enough, you may create variables or functions with the same names which may share the same mutable states which still cause a race condition.

Encapsulation does not mean that you have to hide object data to nowhere. It more about setting diverse levels for accessibility.

There are two divergent about encapsulation(from Wikipedia):

A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.

A language mechanism for restricting direct access to some of the object’s components.

Student database scenario

Imagine you are creating a student database for multiple subjects, later this project could be integrated into the CRM system from the school.

Each student can represent as an object with these properties:

name

grade

class Student { constructor(firstName, grade){ this.name = name; this.grade = grade; } } let student1 = new Student('Jane',20); console.log(student1.name); student1.name = 'April'; console.log(student1.name) //the output is April

The problem here is anytime you want to access the properties in this student1 object, you may change the value accidentally.

To address this, we need to bundling data with methods that provide indirect access to the data.

The common way to do this is using getter and setter.

1. Use getter and setter with ES6 class

The getter and setter functions embody the first definition of encapsulation I have mentioned above: facilitates the bundling of data with the methods (or other functions) operating on that data.

The getter function does not change the value in an object but only reads it. For updating the value, we call the setter function to do so.

display the value by using the getter function and transfer into string type

update the value by using the setter function

JS OOP 3.1 encapsulation constructor function and ES6 class

The outputs are:

“Jane 80” “Jane 100”

Here I initiate a student object with the name ‘Jane’ with grade 80. However, I still can use the dot notation to change the grade value directly.

After calling the getter function, the output has already changed.

Some developer may add an underscore before the properties to remind their colleges that ‘See, this property is private’

let _name; let _grade;

This solution is only validly addressed by a human, not by the code itself. JavaScript does not contain encapsulation keywords such as ‘public’, ‘private’ or ‘protect’.

One way to make a property private is via factory functions.

2. Use factory functions

Factory function can produce(or return) an object without a new keyword.

Furthermore, we can make the properties private.

3.2.1 Problem: you need the find out who has car value among three properties

The outputs are:

“Jane 80” “Jane 80”

I do the same process as my previous codes, but this time, the getter function still return the same value from the setter function.

So the factory function here meet the two definitions of encapsulation:

To operate data with bundling methods(getter and setter functions)

To restrict the direct access to object mechanism(const, and factory function)

We can output the the stu1 object itself to see the what is inside:

[object Object] {

getGrade: function getGrade() {

return grade.toLocaleString();

},

getName: function getName() {

return name.toLocaleString();

},

grade: 100,

setGrade: function setGrade(para) {

return grade = para;

},

setName: function setName(para) {

return name = para;

}

}

No matter how you change the value of grade property, the getter function will give the same value as the last run via the setter function.

This is call closure(or lexical closure). The properties inside the stu1 object are already binding with the factory function after claiming it.

Conclusion

The main purpose of encapsulation is to set up the restrict boundaries from accessing the data.

It seems a good solution of creating private variables with factory functions but it sacrifices the reusability by using class.

There is no best solution(or not yet) to do encapsulation in JavaScript. So it depends on how solid the restriction you want to build and find out the best way to do your project.