Understanding Private Variables in JavaScript Class Constructors
Tags: beginners, javascript
Published: 2020-11-04 09:35:35

[*Follow Me On Twitter @AnnaJMcDougall*](http://www.twitter.com/AnnaJMcDougall)

This week, my class has been looking into factory functions and classes. Naturally, the topic of 'private variables' came up, and has been a source of much confusion. To me, this confusion is similar to the confusion over Closure, which I addressed in [a recent blog post](https://dev.to/annajmcdougall/seriously-though-what-is-closure-5hdn): we use them instinctively, they make total sense to us, but when they're given a name we suddenly feel confused and wonder if we don't really get it after all.

So if, like me, you hear the phrase 'private variable' and you begin to sweat, then let me help clarify what we're talking about and why you probably already use them. 

## Let's set the scene

Let's create a simple `User` class in JavaScript which will form the basis for our examples:

```
class User {
   constructor(name, age, favNumber) {
      return {name, age, favNumber}
   }
}

let firstUser = new User("Anna", 33, 7)
console.log(firstUser.name) // logs "Anna"
```

OK, so we have a super basic class which returns the parameters as properties of the object we create. 

### Side note: Returning parameters within the constructor

You may have noticed in the third line above, that I opted to simply return the parameters in the constructor. This is the same thing as:

```
this.name = name
this.age = age
this.favNumber = favNumber
```

These return values also come in handy later, and for me help me visualise what I'm making 'public' vs what I'm making 'private'. It also helps save some typing, and I'm always in favour of lazin-- uhh, efficiency.

## What is public? What is private?

In the above code, all of our parameters are 'public'. Now, don't let the standard ideas of public and private confuse you: we are referring here to the global scope. We can type into the global scope `firstUser.favNumber` and we will get `7`, because `favNumber` is being returned. In this instance, `name`, `age`, and `favNumber` are all *public*.

So let's create a private variable, a super secret magic number using our super secret Formula For Success™.

```
class User {
  constructor(name, age, favNumber) {
    let superSecretNumber = Math.round((age * favNumber) / name.length);
    function logOutcome() {
      console.log(`Wow! Your secret number is ${superSecretNumber}`);
    }
    return { name, age, favNumber, logOutcome };
  }
}

let firstUser = new User("Anna", 33, 7);
console.log(firstUser.name); // logs "Anna"
console.log(firstUser.superSecretNumber); // WHOMP WHOMP: 'undefined'
firstUser.logOutcome();  // logs "Wow! Your secret number is 58"
```

Voila! That's a private variable in a JavaScript class: `superSecretNumber`, which we cannot access from the global scope. Trying to log `firstUser.superSecretNumber` gives us `undefined`. However, we can also use a Closure (again, read [my blog post](https://dev.to/annajmcdougall/seriously-though-what-is-closure-5hdn) if this is shaky ground for you) in the form of the `logOutcome` function, which accesses this private variable and uses it in some way (in this case, by logging it with a message). If you imagine a much more data-sensitive algorithm, you can see how protecting variables in this way is extremely important.

`superSecretNumber` is not accessible anywhere else in your code, and if you log your object in the browser or elsewhere, you won't see `superSecretNumber` anywhere in the list of properties. It is hidden from 'public' view. Of course, it is still public in the sense that if someone downloaded your code and read through it, they would see you defining the variable and how you did it: this is why it's important not to take your usual/normal understanding of public and private in this instance. 

## One last convention worth noting

Take it or leave it, but it is convention to use an underscore `_` in front of private variables. So in the above example we would name `superSecretNumber` as `_superSecretNumber` instead. There are some libraries that work with this convention so it's worth noting and building into your habits.