What is a Variable?
A variable is a labeled box in your computer's memory that stores a value. You give the box a name, put something in it, and refer to it by that name later in your code.
let userName = "Alice"; // Declare and assign
let userAge = 30;
let isLoggedIn = true;
console.log(userName); // Alice
console.log(userAge); // 30
console.log(isLoggedIn); // true
userName = "Bob"; // Reassign
console.log(userName); // Bob
let – The Modern Default
let was introduced in ES6 (2015) and is the go-to choice for variables whose values will change. It is block-scoped, meaning it only exists within the { } block where it was declared.
let score = 100;
if (true) {
let score = 200; // Different variable — block scope!
console.log(score); // 200
}
console.log(score); // 100 — the outer score is unchanged
// let cannot be redeclared in the same scope
let score = 300; // SyntaxError: Identifier 'score' already declared
const – For Values That Don't Change
const declares a variable that cannot be reassigned after its initial value is set. It is also block-scoped. Use const by default — it communicates intent and prevents accidental reassignment.
const PI = 3.14159;
const MAX_RETRIES = 3;
const SITE_NAME = "ylearner";
console.log(PI); // 3.14159
PI = 3; // TypeError: Assignment to constant variable
// const must be initialized at declaration
const EMPTY; // SyntaxError: Missing initializer in const declaration
// IMPORTANT: const objects/arrays can be mutated!
const user = { name: "Alice" };
user.name = "Bob"; // This is allowed — the binding is const, not the object
console.log(user.name); // Bob
const prevents you from reassigning the variable (pointing it to a new object), but you can still mutate the object's properties. If you need a truly immutable object, use Object.freeze().
var – The Old Way (Avoid It)
var is the original way to declare variables (pre-ES6). It behaves very differently from let and const: it is function-scoped (not block-scoped), can be redeclared, and is hoisted to the top of its function. These quirks cause hard-to-find bugs.
// var is function-scoped — leaks out of blocks!
if (true) {
var leakyVar = "I escape blocks!";
}
console.log(leakyVar); // "I escape blocks!" — no error!
// var can be redeclared (let cannot)
var count = 1;
var count = 2; // No error — silent bug trap
console.log(count); // 2
// var is function-scoped, not block-scoped
function example() {
var x = 10;
}
console.log(x); // ReferenceError: x is not defined
Variable Hoisting Explained
Hoisting is JavaScript's behavior of moving variable (and function) declarations to the top of their scope before code executes. This can lead to surprising results with var.
// What you write:
console.log(name); // undefined (not an error!)
var name = "Alice";
console.log(name); // "Alice"
// What JavaScript actually executes (after hoisting):
var name; // Declaration hoisted to the top
console.log(name); // undefined — declared but not yet assigned
name = "Alice"; // Assignment stays in place
console.log(name); // "Alice"
The Temporal Dead Zone
let and const are also hoisted, but they are not initialized — they exist in the "temporal dead zone" (TDZ) from the start of their block until the declaration is reached. Accessing them in this zone throws a ReferenceError.
// var: hoisted and initialized to undefined
console.log(varVar); // undefined (no error)
var varVar = "hello";
// let: in the temporal dead zone → ReferenceError
console.log(letVar); // ReferenceError: Cannot access 'letVar' before initialization
let letVar = "world";
// const: same as let
console.log(constVar); // ReferenceError
const constVar = "!";
The TDZ is actually a feature, not a bug — it forces you to declare variables before using them, which prevents the confusing undefined behavior of var hoisting. Write clean code and declare your variables at the top of the block they're used in.
Naming Rules and Conventions
JavaScript variable names must follow these rules:
- Can contain letters, digits, underscores (
_), and dollar signs ($) - Must start with a letter,
_, or$— not a digit - Are case-sensitive:
myVarandmyvarare different variables - Cannot be reserved keywords (
let,const,class,return, etc.)
| Convention | Use For | Example |
|---|---|---|
| camelCase | Variables and functions | userName, maxRetries |
| PascalCase | Classes and constructors | UserProfile, HttpClient |
| UPPER_SNAKE_CASE | Constants (never change) | MAX_SIZE, API_KEY |
| _prefix | Private/internal (informal) | _id, _cache |
Multiple Assignment and Swapping
// Declare multiple variables
let x = 1, y = 2, z = 3;
// Swap two variables without a temp variable (destructuring)
let a = "first";
let b = "second";
[a, b] = [b, a];
console.log(a, b); // "second" "first"
// Assign the same value to multiple variables
let width = height = 100; // Avoid — creates global 'height' if not declared!
let width2 = 100;
let height2 = 100; // Prefer explicit declarations
Start with const for every variable. Only switch to let if you find yourself needing to reassign it. Never use var in modern code. This rule keeps your code predictable and intention-clear.
🏋️ Practical Exercise
- Declare a
constcalledBIRTH_YEARwith your birth year, then calculate and log your age usingnew Date().getFullYear() - BIRTH_YEAR. - Declare
let firstNameandlet lastName, then use a template literal to log your full name. - Try to reassign a
constvariable and observe theTypeError. - Demonstrate the temporal dead zone by logging a
letvariable before declaring it — read the error message. - Swap two variables using destructuring assignment:
[a, b] = [b, a].
🔥 Challenge Exercise
Write a script that declares a const object called config with properties siteName, version, and maxUsers. Then add a new property debugMode to it and log the full object. Finally, try to reassign config to a new object and observe the TypeError. Explain in a comment why the property addition worked but the reassignment didn't.
📋 Summary
- Use
constby default; switch toletonly when reassignment is needed; never usevar. letandconstare block-scoped;varis function-scoped and leaks out ofif/forblocks.varis hoisted and initialized toundefined;let/constare in the temporal dead zone until declared.constprevents reassignment but allows mutation of objects and arrays.- Use camelCase for variables and functions, PascalCase for classes, UPPER_SNAKE_CASE for true constants.
Interview Questions
- What is the difference between
let,const, andvar? - What is variable hoisting in JavaScript?
- What is the temporal dead zone?
- Why does
constallow object properties to be changed? - What is the difference between block scope and function scope?
Frequently Asked Questions
No. var's function-scoping and hoisting quirks serve no purpose that let and const don't handle better. The only time you'll encounter var is in legacy code. When maintaining old code, it's generally safe to replace var with let or const, but test thoroughly since subtle scoping differences can exist.
Yes with let: let x; creates a variable with the value undefined. With const, you must provide a value at declaration — const x; is a syntax error. With var, var x; also creates an undefined variable.
In non-strict mode, assigning to an undeclared variable creates a global variable — a major source of bugs. In strict mode ('use strict'; at the top of a file or function), it throws a ReferenceError. Always declare your variables explicitly with let or const.
No, it's just a convention — the JavaScript engine accepts any valid identifier regardless of case. However, following conventions makes your code readable to other JavaScript developers. Linters like ESLint can enforce naming conventions in a team setting.
A variable that is declared but not assigned is undefined: let x; console.log(x); // undefined. A variable that was never declared at all throws a ReferenceError when accessed: console.log(y); // ReferenceError: y is not defined. They are different error conditions.