How To Use Variable Keywords In JavaScript Properly
Tags: javascript, beginners, webdev, node
Published: 2019-10-11 20:17:09

JavaScript can do _lots_ of things; make desktop apps, run web servers, build world-class enterprise applications, make freakin' full-fledged games, and so much more. However, at each of these applications' core, there is __data__. And data is handled by __variables__. In this article, we'll be exploring JavaScript variables and how to use them properly.

Let's get right into it. 

# Variable Scope

Let's take a look at two programs:

```javascript
// Example 1
{
    var superImportantGovernmentPassword = "42";
}

// VS

// Example 2
{
    let superImportantGovernmentPassword = "42";
}

```

> If you're wondering why each of those variables are enclosed in curly brackets `{}`, just know that those curly brackets essentially act as a "container", restricting access to whatever's inside of them. However, as you'll soon see, that isn't always the case...

Let's say there's an evil programmer who got a copy of this code and wanted to publish it to the web for all of his criminal friends to see. He might do something like this:

```javascript
publishSecretPassword(superImportantGovernmentPassword);
```
What'll happen next depends almost entirely on what variable keyword you used to declare `superImportantGovernmentPassword`. You see, in one scenario, the code executed by the evil programmer will work as planned, but in the other case, he'll get this error:

`ReferenceError: superImportantGovernmentPassword is not defined`

Why is this happening?

It all has to do with __variable scope__, and how each keyword treats the data in the sense of that scope. 

## Scope Is A Container

Remember those curly brackets?

```javascript
{
    ...
}
```

Well, in JavaScript, curly brackets are a way of blocking outside access to anything inside of these curly brackets. That's why, in one of the scenarios, the evil programmer gets a `ReferenceError` back; because he , quite literally, couldn't touch `superImportantGovernmentPassword`. 

That's because of the fact that the `superImportantGovernmentPassword` variable _wasn't in the **global scope**_. The **global scope** can be thought of as the place *outside of the container*. Anything outside of the container can be accessed by anybody! However, when you put something inside curly brackets, then you're adding a container to the field and putting something into that container. In our case, we're trying to put `superImportantGovernmentPassword` in a safe *scope* so that people from the outside world can't access it. 

> *But, what if I want to login to my secret FBI server?! I need my password!* - A secret FBI agent

Well, we can fix that...

##  `var` Negates Scope

As you've seen, we can block outside access by adding another *scope* to the program. However, things can get tricky when you use `var` to declare your variables. Remember Example 1?

```javascript
// Example 1
{
    var superImportantGovernmentPassword = "42";
}
```

Well, if you were wondering which scenario lets the evil programmer complete his evil plan, this is it. That's because using `var` **completely negates any scope**! Anything that is declared with the `var` keyword gets put into the global scope, irrespective of where it was declared. You could put 100 nested curly brackets, and the evil programmer would still succeed. 

It's for this reason that, as a general rule, JavaScript programmers...

## NEVER USE `var` TO DECLARE VARIABLES

I'll say it once more: **NEVER USE `var` TO DECLARE YOUR VARIABLES!**

> *But, why?* - You

Because it puts the functionality of your entire program, along with its readability, semantic meaning, and organization into a state of chaos. Imagine a program where *every single function* has access to *every bit of data* in your program; it would cause a lot of issues! For this reason, it is best practice to use the other two keywords we'll be talking about today: `let` and `const`. 

## How to NOT Negate Scope

Let's go back to Example 2:
```javascript
// Example 2
{
    let superImportantGovernmentPassword = "42";
}
```

Here, we use `let` instead of `var`. Now, if that evil programmer tries his dirty trick again, then he'll be met with this error:

`ReferenceError: superImportantGovernmentPassword is not defined`

This is because `let` respects the scope it currently is working inside of, so it doesn't expose our `superImportantGovernmentPassword` variable to the outside world. With that, we've beat the evil programmer and sent him back to his terminal shell. Neat.

## Locking Values In

Let's say one of your top FBI officials is looking to login using that password. He executes his `loginToSecretServer(password)` function, but comes up with an error:

`Sorry! Wrong password. You have 2 more tries, then you're locked out. [This message was written by console.log()]`

Since he knows the password is 42, he goes back to the file where the password is. Lo and behold, it is still 42:

```javascript
...
let superImportantGovernmentPassword = "42";
...
```

What's causing the problem?

Well, he runs a find-and-replace through the repository and finds that `superImportantGovernmentPassword` is referenced in another file. However, the code over there is a little fishy:

```javascript
...
superImportantGovernmentPassword = "2408oifsd8fu08sdg";
...
```

He frowns. Somebody has changed the reference value of the variable, which meant that he was logging in with the WRONG password. He deletes the line of code, but also wants to prevent any future programmers from making the same mistake; how does he do that?

Well, observe what he does next:
```javascript
/// Original password file
{
    const superImportantGovernmentPassword = "42"; // NOTICE THE 'const'
}
```

Wait, what's `const`? You see, `const` is short for "constant", and when you declare a variable with it, it is essentially saying "The value of this variable will remain unchanged (or 'immutable') for as long as it's used". Thanks to this small change, the FBI officer can rest in peace, knowing that any foolish programmers who mistakenly try to change `superImportantGovernmentPassword`'s value indirectly will be met with this message:

`TypeError: Assignment to constant variable.`

# Summary

So, let's summarize what we've learned:

1. Never use `var` to declare variables, because it will let EVERY single part of your program access its value. Instead, use `let`, which respects the scope and prevents access to its value from outside the scope.
2. Scope is like a container; every program starts with a "global scope", where every variable lives by default as if it were in a "container". You can then create "sub-containers" to protect the values of some variables, which lets you prevent fatal errors in your program's logic!
3. Sometimes, you don't want external sources changing the value of your variables. When you want that, use `const`, which locks in the value of your variable completely. 

Thanks for reading. I hope you enjoyed!