Variables

Understand how to declare, initialize, and reassign variables using var, let, and const, and know which to use and why.

Variables are named containers for values — they let a program store data once and refer back to it, update it, and pass it around, which is the foundation of nearly everything JavaScript does.

Declaration, initialization, and reassignment

Declaration is the act of creating a variable name so JavaScript knows it exists, for example let score;. Initialization is giving that variable its first value, either at the same time as declaration (let score = 0;) or afterward (score = 0;). Reassignment is changing a variable's value later on (score = 10;).

A variable that is declared but not yet initialized holds the special value undefined until it is given a value. Understanding these three distinct steps — declare, initialize, reassign — makes it much easier to reason about what a variable actually contains at any given line of code.

var: the original way

var was the only way to declare variables until 2015, and it is still valid JavaScript today, though modern code rarely uses it. Variables declared with var are function-scoped (visible throughout the entire function they're declared in, regardless of block boundaries like if or for) rather than block-scoped, and they can be redeclared with var again in the same scope without an error.

var declarations are also "hoisted" — the declaration itself is conceptually moved to the top of its scope during compilation, so referencing a var variable before its declaration line gives undefined instead of an error, which can hide bugs. These looser rules are exactly why let and const were introduced.

let: modern, reassignable variables

let, introduced in ES2015 (ES6), declares a variable that can be reassigned later but is block-scoped — confined to the nearest enclosing pair of curly braces { }, such as an if block or a for loop body, rather than leaking out to the whole function.

let also cannot be redeclared with let again in the same scope (that throws a SyntaxError), and it is not accessible before its declaration line — attempting to use it earlier throws a ReferenceError, landing in what's called the "temporal dead zone." This stricter behavior catches real mistakes earlier than var would.

const: variables that cannot be reassigned

const, also introduced in ES2015, works like let (block-scoped, not hoisted the same lenient way as var) but additionally cannot be reassigned after its initial value is set — attempting to do so throws a TypeError. A const variable must also be initialized at the moment it is declared; const x; alone is a SyntaxError.

Importantly, const prevents reassigning the variable itself, not necessarily changing what it contains: if a const holds an object or array, the properties or elements inside that object/array can still be modified — only the variable cannot be pointed at a different object or array entirely.

Scope and best practices

Scope determines where in your code a variable is visible and usable. Block scope (let/const) is generally easier to reason about than function scope (var) because a variable's visibility matches the braces you can see on screen.

The widely recommended modern convention is: use const by default for every variable, and only switch to let when you know you will need to reassign that variable later (like a loop counter or a running total). Avoid var entirely in new code — it exists today mainly for backward compatibility with old codebases.

Variable declaration forms

A variable name must start with a letter, underscore (_), or dollar sign ($), and cannot start with a digit. JavaScript variable names are case-sensitive: score and Score are two different variables. By convention, use camelCase for variable names (totalPrice, not total_price or TotalPrice).

var oldStyle = "avoid in new code";

let counter = 0;
counter = counter + 1; // reassignment allowed

const PI = 3.14159;
// PI = 3; // TypeError: Assignment to constant variable.

Code Examples

This shows let being declared, initialized with a starting value, and then reassigned to a new value. Expected result: maria maria99 username = "maria99"; reassigns the existing variable — no let or const keyword is used again here.

This clarifies a subtle but important point: const blocks reassigning the variable itself, but it does not freeze the contents of an object or array stored inside it. Expected result: { name: 'Sam', age: 26 } Error: Assignment to constant variable.

user.age = 26; is allowed, but user = { ... }; throws a TypeError because it tries to point the const variable at a new object.

let username = "maria";
console.log(username);

username = "maria99";
console.log(username);
const user = { name: "Sam", age: 25 };
user.age = 26; // allowed: modifying a property
console.log(user);

try {
  user = { name: "Alex", age: 30 }; // not allowed: reassigning the variable
} catch (error) {
  console.log("Error:", error.message);
}

Scope: var vs let/const

var ignores block boundaries and is visible throughout the function; let and const are confined to the block where they were declared.

function demo() {
  if (true) {
    var a = 1;   // function-scoped -> visible for the whole function
    let b = 2;   // block-scoped   -> only visible inside these { }
  }
  console.log(a); // 1 (works)
  console.log(b); // ReferenceError: b is not defined
}

Important Rules

Prefer const by default; use let only for variables you know will be reassigned; avoid var in new code.

let and const are block-scoped (confined to the nearest { }); var is function-scoped.

const must be initialized when declared and cannot be reassigned afterward — but objects/arrays it holds can still be mutated.

Using a let or const variable before its declaration line throws a ReferenceError (the temporal dead zone); var instead silently gives undefined.

Where this shows up

Modern JavaScript style guides and linters (like ESLint's prefer-const rule) enforce the const-by-default, let-when-needed, no-var convention across virtually every professional codebase, because it makes code easier to reason about and catches accidental reassignment bugs immediately.

const total; total = 0;

let total = 0; // or: const total = 0; if it will never change const must be given a value at the moment it is declared — declaring it without an initial value is a SyntaxError.

for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); } // logs 3, 3, 3 for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); } // logs 0, 1, 2 var is function-scoped, so all three callbacks share the same single i, which has finished looping to 3 by the time they run; let creates a fresh, block-scoped i for each iteration.

[Multiple Choice] Which statement about const is correct? A. A const variable's value can never change in any way B. A const variable cannot be reassigned, but an object or array it holds can still be mutated C. const variables are function-scoped like var D. const variables can be used before the line where they are declared

B. A const variable cannot be reassigned, but an object or array it holds can still be mutated — const only prevents reassigning the variable itself to a new value; if it holds an object or array, that object's properties or elements can still be changed.

[True / False] Variables declared with let are function-scoped, just like var. A. True B. False

B. False — False. let (and const) are block-scoped — confined to the nearest enclosing { } — while var is function-scoped.

Declare a const named siteName with the value "SampleApp", and a let named visitorCount starting at 0. Then increase visitorCount by 1 and log both variables.

const siteName = "SampleApp"; let visitorCount = 0; visitorCount = visitorCount + 1; console.log(siteName, visitorCount);

Only one of the two variables should be able to change after its initial value.