Dataslope logoDataslope

Variables and Program State

How JavaScript names values, why `let` and `const` exist (and `var` mostly doesn't), and what it means for a program to have "state".

A program made only of values would be useless. The interesting thing programs do is remember. A variable is how a program remembers a value and gives it a name.

What a variable really is

A variable is a named slot that holds a value. You can think of it as a labelled box:

When you write:

const age = 28;

…you are telling the runtime: create a box, label it age, and put the value 28 inside it. From now on, anywhere your code mentions age, the runtime looks in that box and uses what it finds.

The three keywords: const, let, var

JavaScript has three keywords for declaring variables. In modern code, only two are commonly used:

  • const — declares a variable whose binding cannot be reassigned.
  • let — declares a variable whose binding can be reassigned.
  • var — the old, original keyword, kept for backwards compatibility. Avoid it in new code.

The rule of thumb is simple and powerful:

Use const by default. Use let only when you actually need to reassign. Never use var.

The reason is that const documents your intent. When a reader sees const, they know the binding will never change. That makes the program easier to reason about.

Code Block
JavaScript ES2023+

That last block is important. const makes the variable immutable (you cannot point it at a different value), but it does not freeze the value inside. If the value is a mutable object (like an array), you can still change its contents.

Declaration vs initialisation vs assignment

Three words that beginners often mix up:

  • Declaration — telling JavaScript a variable exists. let x;
  • Initialisation — giving the variable its first value at declaration. let x = 5;
  • Assignment — changing the value of an already-declared variable. x = 7; (no let/const keyword).
Code Block
JavaScript ES2023+

Naming variables

Good variable names are the single biggest factor in code readability. Some rules and conventions:

  1. Names must start with a letter, _, or $. They can then contain letters, digits, _, or $. No spaces, no hyphens.
  2. JavaScript is case-sensitive. userName and username are different names.
  3. The standard style is camelCase for variables and functions: userName, totalPrice, currentItem.
  4. Constants that are truly fixed (like configuration values) are often SCREAMING_SNAKE_CASE: MAX_RETRIES, PI.
  5. Names should describe the value, not the type. Write users, not userArray. Write count, not countNumber.
  6. Avoid single letters except as loop counters (i, j, k) or for very short mathematical formulas.
Code Block
JavaScript ES2023+

Both programs do exactly the same work. One reads itself out loud. One requires the reader to guess what each letter means. The first kind of code is debt; the second kind is an asset.

Program state: variables changing over time

The collection of all the variables a program has at any moment, together with the values inside them, is called the state of the program. As the program runs, the state changes: variables get new values, new variables are created, old ones go away.

A useful exercise is to draw a state table as a program runs. Each row is a snapshot after one statement. Each column is a variable.

Take this program:

let x = 5;
let y = 10;
let z = x + y;
x = z;
y = x - 1;
After linexyz
15
2510
351015
4151015
5151415

This kind of bookkeeping looks tedious, but it is the exact same thing the runtime is doing internally. Practising it on small examples teaches you to "see" state.

Run the program and confirm:

Code Block
JavaScript ES2023+

Block scope: where a variable lives

A let or const declared inside { ... } only exists inside those braces. This is called block scope.

Code Block
JavaScript ES2023+

This may look pedantic, but block scoping prevents an entire category of bugs. A variable used only inside a loop should not "leak" out of the loop. A temporary value in an if should not pollute the rest of the function.

We will spend an entire later chapter on scope; this is just a first taste.

Why var is discouraged

var was the original variable keyword. It has two surprising behaviours that let and const were designed to fix:

  1. var is function-scoped, not block-scoped. A var declared inside an if is still visible outside the if.
  2. var is "hoisted", meaning the declaration is silently moved to the top of the enclosing function. You can refer to a var before it appears in the source, and you'll get undefined instead of an error.

These behaviours are surprising, error-prone, and rarely what you want. New code essentially never uses var. You may see it in old codebases, and that's fine; you just don't need to write it.

Constants of convenience vs constants of meaning

It is worth distinguishing two reasons to use const:

  • Constants of meaning: values that are fundamentally fixed by the problem. const PI = 3.14159; const MAX_USERS = 100; Usually given SCREAMING_SNAKE_CASE names.
  • Constants of convenience: ordinary variables that happen not to be reassigned in this function. const total = bill + tip; Standard camelCase is fine.

The second kind is far more common in modern code. Most local variables don't need to be reassigned, so they are declared with const.

A small example tying it together

Let's track a tiny "user session" with three variables, and see how state evolves over the program.

Code Block
JavaScript ES2023+

That is a tiny state machine: three variables, evolving over time, in response to events. Almost every interactive program in the world — your email client, your phone's home screen, a video game, this very web page — is, at its core, a much bigger version of this.

Challenge

Challenge
JavaScript ES2023+
Bank account state

The harness defines a starting balance of 100 and asks you to perform a series of operations on it.

Write the code so that after running the operations in order, the variables balance, deposits, and withdrawals end up with the expected values:

  1. Deposit 50 (balance up, deposits += 50).
  2. Deposit 30 (balance up, deposits += 30).
  3. Withdraw 40 (balance down, withdrawals += 40).
  4. Withdraw 10 (balance down, withdrawals += 10).

After all four steps:

  • balance should be 130
  • deposits should be 80
  • withdrawals should be 50

QuestionSelect one

Which of the following best describes the recommended way to declare variables in modern JavaScript?

Always use var for backwards compatibility

Use let for everything to keep things flexible

Use const by default; switch to let only when you actually need to reassign; avoid var

Use const for primitives and let for objects

On this page