Variables & Constants
Variables and constants are the most basic way a program stores and refers to data. Everything from arrays to objects is, at some level, a more elaborate way of organizing named storage.
A variable is a named piece of storage that holds a value, which can change over the program's lifetime. A constant is a named piece of storage whose value is fixed once set and cannot be changed afterward (in languages that enforce this).
Names make code readable and let you refer to a piece of data repeatedly without rewriting its literal value. Constants additionally protect against accidental changes to values that should never change (like the number of days in a week, or a fixed configuration limit), and they document intent.
Every program uses variables — to hold user input, intermediate calculation results, loop counters, configuration values, and so on. Constants are used for values like mathematical constants, fixed limits, and configuration flags that must not be modified after they're set.
A variable is like a labeled box you can open, look inside, and swap the contents of whenever you want. A constant is like a labeled, sealed box — you can still read the label and look inside, but once it's sealed, you can never put something different in.
age can be reassigned freely because it's declared as an ordinary variable. PI is declared const, so the compiler rejects any later attempt to change it.
A variable declaration typically reserves storage and associates a name (and, in static languages, a type) with it; an assignment stores a value into that storage; these are conceptually distinct steps even when combined in one line of code (int x = 5;).
Mutability is about whether a value can change after creation, and is a related but distinct concept from constants — some languages distinguish 'the variable binding can't be reassigned' (like JavaScript's const, which prevents reassigning the variable) from 'the value itself can't be mutated' (a const array in JavaScript can still have its contents changed, just not be pointed at a different array).
Naming conventions (camelCase, snake_case, PascalCase) aren't enforced by most compilers, but are strongly enforced by convention and tooling (linters) within a language's ecosystem, and mixing conventions inconsistently hurts readability.
A variable's declared type (in static languages) constrains what values it can later hold; a dynamically typed variable is really just a name that can be rebound to point at values of any type over time.
Using a mutable variable where a constant is intended, allowing accidental reassignment somewhere deep in a large codebase that's hard to trace back.
Confusing const (JavaScript) with true immutability — const only prevents reassigning the variable itself, not mutating an object or array's contents through that variable.
Choosing unclear, overly short variable names (x, tmp, data2) that make code hard to review or debug months later.
Shadowing an outer variable with an inner one of the same name unintentionally, causing confusing bugs where the 'wrong' variable is modified or read.
Declaring configuration values (a maximum retry count, an API base URL) as constants so their values are protected and immediately recognizable as fixed throughout the codebase.
Using descriptive variable names (remainingAttempts instead of n) specifically to make code self-documenting and easier for teammates (and your future self) to understand.
Where variables actually live in memory Depending on how and where they're declared, variables can live in the stack (local variables, automatically reclaimed when their function returns), the heap (dynamically allocated data with a manually or automatically managed lifetime), or static/global storage (fixed for the program's entire lifetime) — the exact placement and its consequences are covered in full in the future Memory & Program Execution module.
Constant folding at compile time Many compilers evaluate expressions involving only constants at compile time (constant folding) rather than at runtime — const int SIZE = 10 * 10; may simply become the literal 100 embedded directly in the generated machine code, with no runtime multiplication happening at all. This is one of the compiler optimizations covered in the future Compiler Optimization module.
Immutability and compiler/runtime optimization Knowing a value can never change lets a compiler or runtime make stronger optimizations and safety guarantees — for instance, immutable data can be freely shared across threads without synchronization, since there's no possibility of one thread observing a partially updated value written by another.
What's the difference between a variable and a constant?
A variable's stored value can be changed after it's set; a constant's value is fixed once assigned, and the language (or compiler) enforces that it can never be reassigned.
In JavaScript, why can you still push a new item onto a const array?
Because const only prevents reassigning the variable name to a different array (or value) entirely — it does not make the array's contents immutable. Pushing an item mutates the existing array object, which const doesn't restrict.
What is variable shadowing?
When an inner scope (like a function or a block) declares a variable with the same name as one in an outer scope, the inner declaration 'shadows' — temporarily hides — the outer one within that inner scope, which can lead to confusing bugs if unintentional.
int age = 25; // variable — can change
age = 26; // legal
const double PI = 3.14159; // constant
PI = 3.0; // compile-time error