Object oriented JavaScript – encapsulation

In previous post, I wrote about inheritance in JavaScript. This time, I will cover another important concept in object-oriented programming – encapsulation. Class-based languages like Java and C++ provide built-in keywords like private  and protected  which facilitate implementing much of the concepts covered by encapsulation. By contrast, JavaScript, being prototype-based language, does not provide these features. Still, it is possible to implement encapsulation in JavaScript and this post will cover how that can be achieved.

Scopes in JavaScript

Before we get into the details of implementing encapsulation, we will first explain the concept of scopes. This is the basis for understanding encapsulation, and also for some other concepts in JavaScript, so understanding it will improve your overall understanding of the language. Consider the following code snippet:

In the first line, we declare a variable x  in global scope. This scope is accessible from everywhere in JavaScript program. Basically, whenever you declare a variable outside of function, it is available in global scope and accessible by everyone.

In line 4, within the function, we declare the variable local . When ever variable is declared inside a function, it belongs to local scope, and can only be accessed from within that function scope. This is similar to what you might expect in C-based language, but the difference is that in JavaScript, scopes are created only within functions, not within if/for/while  blocks.  In line 6, if we try to access variable local, it will be undefined, because we’re accessing it out of it’s defined scope.

Scopes can also be nested. That means, we can create another function within a function. In that case, inner function will have access to all variables of outer function, but not vice-versa. This is tha basis for concept of closures in JavaScript.

Basically, closure is a function reference returned from a function. Meaning, a function does not return a value, but another function which, when invoked, has access to scope of it’s enclosing function. In this code snippet, we define local variable local , and return it’s value by closure. This way, we can access this value by invoking return function. Note the extra () operator in closure('test message')() . It means that we are invoking the function returned from  closure.

Encapsulating local variables

Now that we understand scopes, we will see how they can be used to implement encapsulation. Let’s start with creating a simple object. If you are not familiar with creating objects in JavaScript, check out this post.

As you can see from this example, when we create object in JavaScript, it’s properties are public by default. We can read and write these properties without problems. Since JavaScript has no concept of access modifiers (like private / public ), we need another way to achieve this feature.

Let’s say we want to prefix property word  with certain text when ever it is set. We can use setter method to achieve this.

Here, we create a pair of getter/setter methods to read and write property. In setWords  method, we prepend “prefix” to the text we set. Unfortunately, this approach does not work, since clients can still access the property directly:

The way to prevent this is to use closures. The final solution would look like this:

In this sample, we assign return value of the function to variable text . Notice the () pair in the last line. This means that we actually invoke the function and assign it’s value to variable text . Inside the function, we create a local variable which is accessible only within the function scope. Finally, the function return value is an object which has access to function’s internal scope, and thus can access internal variable.

The effects of this can be verified with the following code snippet:

As you can see, event after the property is set directly, the getter still return original value, which means that direct change is applied. Still there is a caveat here. Consider this:

This line will produce direct access: direct value . Why is this? Because, when we directly assigned value to property words , we implicitly created new property called words  at object level scope. This is possible due to dynamic nature of JavaScript. Notice that this property is not the same as one defined in function scope, but completely separate entity.

Why is this so weird?

People accustomed to class-based languages will probably find this way of encapsulation ridiculous (I am one of them 🙂 ). But, the nature of JavaScript is such that it requires significant shift in way of thinking compared to strongly-typed, class-based languages. Once you wrap your hand about oddities of JavaScript, you will find it’s not such a bad language after all.

Complete source code for this post can be found on Github.

Related posts

One thought on “Object oriented JavaScript – encapsulation

Leave a Reply

Your email address will not be published. Required fields are marked *