In a past life (i.e. for 8 years after college before realizing how important money is), I was a college English teacher. I still enjoy teaching (in the rare opportunities that arise) and have had intentions for some time to try to bring that discipline into my current line of work by doing a series of more introductory-themed posts. Today I'm going to look at variables in Javascript, primarily what they are and how they work, but I will address variable scoping as well.

Remember in Math class when you had to "Solve for x"? "x" is a variable. It's an unknown value represented by a label. Programming variables work the same way. Let's not worry too much about variable names, but in short, variables can contain letters and/or numbers and should communicate what the variables are being used for.

Variables, in technical terms, are values that have been allocated space in computer memory with a label that points to that memory location so the value can be recalled. Which is a super non-beginnery way to explain them. So here's a metaphor. Think of variables as containers. You can put things in the containers and label them and then when you need them later, you know which is which based on the label, and the contents are there waiting for you. For example, we have a sugar container and a flour container in our kitchen right now. I know what's in them because they say "Sugar" and "Flour" on them. In programming terminology, when we put flour in the container labeled "Flour," we're assigning a value to the variable. Later, when we need to use some flour to make dessert, we're accessing the variable's value.

Variables can be used to store intermediate calculations (like in Math), but they can also be used to clarify program logic. For example, what's more clear?

result = 2 * 60 * 60 * 24 * 365  

or

seconds_in_a_minute = 60  
minutes_in_an_hour = 60  
hours_in_a_day = 24  
days_in_a_year = 365  
seconds_in_two_years = seconds_in_a_minute * minutes_in_an_hour * hours_in_a_day * days_in_a_year * 2  

These do the same thing, but one is much more explicit about programmer intent, which is just as important as (maybe more important than) program logic. But I'm getting a little ahead of myself. Let's talk about how to actually use variables in Javascript.

For a long time, Javascript had only one keyword to indicate a variable: var. Declaring a variable included using the var keyword in conjunction with a variable name. Like this:

var count;  

Many times (but not always) the assignation occurs in the same statement:

var count = 12;  

What's happening here is we're telling Javascript that we need a container for a value, that we want to name that container "count," and that the value is 12. We can also do this in multiple steps:

var count;  
count = 12;  

Notice that we only need to use var the first time. Using var every time would be like buying a new container every time we need to refill the flour. The container already exists; we just need to change the contents.

But var has some . . . issues. Without going into detail, var is scoped somewhat unpredictably, at least compared to other languages. Additionally, var can be error prone (from a developer perspective). The following does not cause an error (and you might want it to):

var count = 12;  
var count = 13;  

In this example count is now 13. But we didn't actually change the value assigned to count. We actually created a whole new variable also named count and assigned it a new value, essentially blowing away the old one (the original count value is actually still there in memory, but with no way to access it as the label was moved to another container - to continue the metaphor, this is kinda like when you go down in your parents' basement and there's just a bunch of jars or cans with no labels and you have no idea what's in them). This kind of variable redefinition is almost always a developer mistake.

To counter the issues with var, a recent (2016) update to the Javascript language introduced two new variable declaration keywords: const and let. Let's look at each in turn.

const is short for "constant," a programming term that refers a variable that, once initialized, cannot be changed. Many other languages have contants, but for a long time Javascript did not. const is used exactly like var, except that if you try to change the value, it causes an error:

const count = 12; // ok  
count = 13; // ERROR!  

I usually use const for a) actual constant values that never change (the number of seconds in a year calculation above would be a good candidate) and b) variables that come from third-party libraries (since you wouldn't want to modify them).

let is closer to var in that you can reassign the value of the variable, but it doesn't let you redefine the variable reference the way var does:

let count = 12; // ok  
count = 13; // still ok  
let count = 14; // ERROR  

Additionally, const and let are both block scoped. At last we come to scoping, which is difficult to understand as a beginner, but let's use our same metaphor to see if we can simplify it. Let's say you've got your container of flour (labeled "Flour"), and you store it in a walk-in pantry. If you are standing in the kitchen, you can't access it. You have to walk into the pantry to get it. It is scoped to the pantry. "Scope" is a word we use to refer to a block (or part) of a program. Variable scoping refers to the block of a program in which a variable can be accessed. Blocks in javascript are almost always formed with the brace characters { and }, for example in functions, if statements, case statements, while and for loops, and other similar constructs.

In short, when you use let and const, the variables you declare are accessible in the current block and in any sub-blocks. It may help you to think about indentation when you consider this. You usually have access to variables defined at the same indentation level or at a higher indentation level (provided you don't pass a { or } going to them). Here are some simple examples using let to attempt to illustrate block scoping.

First, let's define a variable in an outer scope (the highest scope is also called global scope) and reference it in a sub-scope.

let count = 12;

if (count > 10) {  
  count = 20;
}

Here we declare count and then create a sub scope (or nested scope/block) inside the if statement (notice the presence of { and } around the indented line). Because we defined count at a higher level, we can use it (and assign to it), inside the inner block. But the reverse isn't true. The following is an error:

if (someCondition) {  
  let count = 12;
}

console.log(count); // ReferenceError: count is not defined  

This is probably hard to grasp because this isn't how English and other written languages work. We read from top to bottom, so since we've encountered "count" in our reading, it feels like we should be able to use it after the if statement. But we can't because the declaration (let count) occurred inside the if block. count is scoped to that if block and can't be used outside of it. Here you can see the indentation principle at work. let count is indented but console.log(count) is not. Here's another example:

let count = 12;

if (someCondition) {  
  let count = 13;
}

console.log(count);  

What is the value of count at the end of this code?
a. 12
b. 13
c. Something else
d. This is an error

If you're new to Javascript, I'm guessing your first thought is 13, followed closely by "This is an error" since I even gave an example earlier using let that set count to 12 and then replaced it with 13, and said then that it was an error. But the answer is 12. We define a count variable in the outer scope and set its value to 12. Then we start a new block with the if statement. Inside that block, we declare another count variable. This is not an error because it's a separate scope. Each scope can have it's own version of count, the same way multiple rooms in your house might have a kleenex box with different quantities of kleenex in each. Note that inside the if block, using the variable count is using the one assigned the value 13, even though the outer one would also normally be accessible. The closest container with a label will always take precedence. In programming, this is called "variable shadowing." The inner count variable shadows the outer count variable making it inaccessible inside the if block. Let's add some logging to make it more clear:

let count = 12;  
console.log(count); // logs 12

if (someCondition) {  
  let count = 13;
  console.log(count); // logs 13
  count = 14;
  console.log(count); // logs 14
}

console.log(count); // logs 12  

As I mentioned earlier, the top-level scope is also called the global scope. Variables defined in the global scope (at least in the browser) are global variables. For example, we can define a variable in one script and use it in another as long as it is defined in the global scope:

<script>  
  let count = 12;
</script>  
<script>  
  console.log(count); // logs 12
</script>  

Not to go too deep in a beginner's post, but in case anyone more intermediate reads this, this is the reason that Javascript programmers use immediately invoked function expressions: it creates a nested scope and prevents defined variables from becoming global variables, e.g.:

<script>  
(function() {
  // Now we're in a nested block, so variables defined
  // here will not be global. For all intents and
  // purposes, count is a private variable. No one can
  // use it outside of this script.
  let count = 12;
})();
</script>  
<script>  
  console.log(count); // ReferenceError: count is not defined.
</script>  

var's scoping is different. I won't try to explain its full intricacies because that would require an explanation of variable hoisting, but suffice it to say that var's scoping is less predictable. var is not block scoped, but function scoped (or global if defined in the global scope). That means that inside a function a variable defined with var is always accessible, regardless of where in the function it is defined:

function doSomething() {  
  if (someCondition) {
    var count = 12;
  }

  console.log(count);
}

This is NOT an error (it would be with let or const). Because var is function scoped, the fact that it's defined inside an if block does not matter. It is accessible anywhere inside the function and therefore correctly logged at the end of the function. Do NOT rely on this behavior, however. Javascript is basically the only language that has scoping of this kind (all the other languages I've interacted with have more traditional block scoping). let and const were added to Javascript because function scoping is error prone and counter-intuitive (once you get used to how scopes work).

In general, if you are able to use let and const, you should prefer them to var. I say "if you are able" because browser support for new features can sometimes (read: always) be inconsistent. caniuse.com suggests let and const are pretty well supported unless you're going back to older versions of certain browsers (which shall remain nameless).

Hopefully, these examples and explanations have helped you understand Javascript variables and some of their idiosyncrasies. If you have questions, please feel free to ask them here in comments and I will do my best to answer them in a timely matter.