Problem statement

JavaScript objects are really just a collection of properties. Using either the object literal syntax or a constructor, objects can be created and properties can be added with ease. Here is a code sample:

//object literal syntax
var person1 = {
  firstName: 'alex',
  lastName: 'ritzcovan'
}

//constructor syntax
function Person(first, last) {
  this.firstName = first;
  this.lastName = last);
}

//create a new person using our constructor
var person2 = new Person('alex', 'ritzcovan');

Each of these methods gives us the same result. We have a new object that has firstName and lastName properties. That’s all well and good and it certainly was easy but that ease comes at a cost.

What if I did the following?

delete person.firstName;

Executing this code does what you would think. It deletes the firstName property from the object. While this may be handy in some instances, more often than not you want the properties you define on your JavaScript object to be private.

Direct access from the outside world takes away your ability to control the value stored in the property.

This is why so many popular object-oriented languages provide the private keyword. Once a variable is declared as private in those languages, the programmer creates get and set functions to get and set the value. It gives the programmer control over the values being assigned and allows for other features such as logging when the value is get or set.

Unfortunately, JavaScript does not provide us with any syntactic features to emulate the private keyword. It does, however, provide us with closures. Using closures, we can emulate private properties. Before we look at how we can do that, let’s make sure we understand closures.

Closures defined

The MDN documentation defines a closure as follows:

closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

MDN docs

I don’t know about you but when I was learning about closures, this definition left me feeling a little like this:

Lost in the sauce

Here is how I like to think about it:

A closure is created every time a function is called. It contains the function definition as well as the surrounding state. Where the function is defined in the code determines what is included in the closure.

Let’s look at some code

//GLOBAL SCOPE
var ten = 10;

function makeAdder(num) { 
  // OUTER SCOPE
  
  function add(num2) {
    // INNER SCOPE
    console.log(ten); //<-- we can still see ten here
    return num + num2;
  }
  return add;
}

var adder1 = makeAdder(10);
var adder2 = makeAdder(20);

console.log(adder1(10));
console.log(adder2(500));

Let’s take this code apart.

First, we declare a variable named ten in the global scope.

Next, we have the makeAdder() function that takes a number as an argument. Within makeAdder() we define another function called add().

Within add() we just print the value of ten (just to show that we can still see it) and return the result of simple addition.

On the next line, we return the add function and the makeAdder() function exits.

Just a moment ago we said that you can determine what will be in a closure by looking at where it’s defined. Well, by looking at the add method, we can see that we are going to have access to:

  1. the global variable ten defined in the GLOBAL SCOPE
  2. the num argument passed into makeAdder() – even after makeAdder() exits. defined in the OUTER SCOPE

This is some of the magic of closures. You have access to values after the functions in which they are defined have finished executing.

Next, we create 2 new adders, passing the value we want to be saved in the num parameter by calling makeAdder(10) and makeAdder(20).

The functions that are returned are saved to the adder1 and adder2 variables respectively. Next, we execute adder1 and adder2 (they are references to functions), passing the value that we want to be added. Looking at the console we see the following output.

the result from our closure

First, we see 10. This is printed when the add function prints the value of the global variable ten. You wouldn’t do this in practice. This is just to show that we still have access to it in our closure.

We then see the first call to add() via the adder1 reference.

console.log(adder1(10));

The closure remembers the value passed as num and we get 20 in the console. Pretty cool. The same process happens again for adder2 and 520 prints to the console.

We have effectively created a private variable, num, with our call to makeAdder(). We don’t have the ability to change the value in num, but we know it’s there because our addition is correct. We can use this knowledge to simulate a private variable.

Solution: creating our private variable

Now that we know what a closure is and how it works, let’s put it to work. Take a look at this code:

let myTest = (function () {
  let _name = '';
  getName = function () {
    return _name;
  }
  setName = function (newName) {
    newName === 'bob' ?
	_name = 'robert' :
	_name = newName;
  }
  return {
	getName: getName,
	setName: setName
  }
}());	

What we’re using here is called the Revealing Module Pattern. It’s a slightly modified version of the popular Module Pattern.

Let’s analyze what’s happening.

First, we define what we want our module to be called. In this case, we are calling it myTest. We set myTest equal to the result of an Immediately Invoked Function Expression or IIFE (pronounced if-e). Inside the function definition, we have our private _name variable, a getName function, and a setName function. Finally, we return an object literal that essentially contains pointers to our functions.

You may be asking “how do I know _name is private?” We know its private because it’s hidden inside the closure that we are creating with the IIFE.

The object literal that’s returned is essentially your public-facing API. Whatever you return here is what is accessible externally. Since we are not exposing the_name variable, we can be confident that it’s private. Let’s test it out!

myTest.setName('alex');
console.log(myTest.getName());

console.log(myTest._name);

myTest.setName('bob');
console.log(myTest.getName());

Immediately following the code above, we call setName on myTest. Here are the results that we get in the console:

You can see in the output that we successfully set the name to alex and retrieved it.

Then we attempt to access the _name variable directly and get undefined. Our private variable works!!

We then set the name again to bob. In our setName function we check the value and update it to robert if the passed value is bob. You can imagine doing checking like this if you expect a certain kind of value in your setter.

We have successfully emulated a private variable using closure. Additionally, the only variable that we have introduced into the global space is myTest. Using this method makes it easy to avoid naming collisions in the global space.

To read more about closures, JavaScript patterns, and other great JS stuff, check out these links:

MDN – FREE

Adequately Good – FREE

Addy Osmani’s great book -FREE

Functional Programming in JavaScript – PAID

Secrets of the JavaScript Ninja – PAID

I also did a video on youtube a while back covering the revealing module pattern. Check it out here if you’re interested

Thanks for reading!