You will be able to choose between var, let, and const in JavaScript and explain how each keyword affects scope, hoisting, and reassignment.
What it is
JavaScript uses declaration keywords to create variables. var is the older keyword and is function-scoped: a variable declared with var is visible throughout the enclosing function, even if it is declared inside an if block or loop. let and const are block-scoped: they are visible only inside the nearest pair of curly braces, such as a function body, loop body, or conditional block.
All three are hoisted, but they behave differently before their declaration line. A var declaration is hoisted and initialized as undefined. A let or const declaration is hoisted but not initialized; accessing it before its declaration causes a temporal dead zone error. const also requires an initializer and prevents reassignment of the binding.
Related terms include scope, hoisting, reassignment, redeclaration, and binding.
Why it matters
- It helps you avoid accidental variable leaks from blocks and loops.
- It makes code easier to reason about by limiting where a value can change.
- It prevents common bugs caused by
varbeing visible outside its intended block. - It lets you signal intent:
constfor values that should not be reassigned,letfor values that will change. - It improves debugging because block-scoped variables are easier to track.
Syntax or steps
The smallest useful pattern is to declare a variable once, then use it inside the same block:
const name = "Ada";
let count = 0;
count = count + 1;
Use const first. If you need to reassign the variable, use let. Avoid var in new code unless you are maintaining older code that depends on function scope or hoisting.
Example
function report() {
var old = "function";
let current = "block";
const PI = 3.14;
if (true) {
let current = "inner";
console.log(current); // inner
console.log(old); // function
console.log(PI); // 3.14
}
console.log(current); // block
}
report();
Part by part:
var oldis function-scoped, so it is visible inside theifblock.- The outer
let currentis block-scoped to the function body. - The inner
let currentcreates a new variable inside theifblock; it does not change the outer one. const PIcannot be reassigned, but it can be read from nested blocks.- The final
console.log(current)prints"block"because the inner variable disappeared when theifblock ended.
Common mistakes
- Using
varinside a block and expecting block scope. Fix: useletorconstwhen the variable should stay inside the block. - Reassigning a
constprimitive. Fix: useletif the value must change. - Assuming
constfreezes objects. Fix: remember thatconstprevents reassignment of the variable, not mutation of the object's properties. - Declaring the same variable twice with
letorconstin the same scope. Fix: rename one variable or move it into a different block.
When to use it
The closest alternatives are var, let, and const. Modern JavaScript usually prefers const by default and let when reassignment is needed.
| Keyword | Scope | Reassign? | Redeclare in same scope? | Use when |
|---|---|---|---|---|
var | Function or global | Yes | Yes | Legacy code or intentional function scope |
let | Block | Yes | No | The value will change |
const | Block | No | No | The binding should not be reassigned |
Practice
- Guided exercise: Write a function that declares
const city = "Paris", then useslet visits = 0and increases it twice. Expected output:2. - Challenge: Fix this code so the loop variable does not leak outside the loop:
for (var i = 0; i < 3; i++) { console.log(i); }. Hint: replacevarwithlet.
Quick check
Question: Why does const user = { name: "Ada" }; user.name = "Grace"; not throw an error?
Answer: Because const prevents reassigning the user binding, but it does not prevent changing properties of the object that the binding points to.
Summary
var is function-scoped and hoisted as undefined, while let and const are block-scoped and protected by the temporal dead zone. Prefer const for values that should not be reassigned and let for values that will change.