JavaScript Variables
Variables are containers for storing data values. In JavaScript, you declare variables using var, let, or const. Understanding the differences between these keywords is essential for writing bug-free code.
What are Variables?
Think of variables as labeled boxes where you can store information. Each box has a name (the variable name) and can hold a value (like a number, text, or more complex data).
// Creating a variable is like labeling a box
let message = "Hello, World!";
// You can read the value
console.log(message); // "Hello, World!"
// And change it (with let)
message = "Goodbye!";
console.log(message); // "Goodbye!"Three Ways to Declare Variables
JavaScript provides three keywords for declaring variables. Each has different behaviors regarding scope, hoisting, and reassignment.
var - The Original Way
var was the only way to declare variables before ES6 (2015). It's function-scoped and hoisted to the top of its scope.
var still works, it has confusing scoping behavior that can lead to bugs. Use let or const instead. let - Block-Scoped Variables
let declares a block-scoped variable that can be reassigned. Use it when you know the value will change.
let count = 0;
count = 1; // OK - reassignment allowed
count = 2; // OK
let count = 3; // ERROR - cannot redeclareconst - Constants
const declares a block-scoped variable that cannot be reassigned. However, if the value is an object or array, its properties can still be modified.
const PI = 3.14159;
PI = 3.14; // ERROR - cannot reassign
const user = { name: "Alice" };
user.name = "Bob"; // OK - modifying property
user = {}; // ERROR - cannot reassign referenceconst by default. Only use let when you know the variable needs to be reassigned. This makes your code more predictable and easier to reason about. Try It Yourself
Run this example to see how var, let, and const behave:
// Using var (function-scoped)
var name = "Alice";
console.log("var name:", name);
// Using let (block-scoped, can be reassigned)
let age = 25;
console.log("let age:", age);
age = 26; // Reassignment is allowed
console.log("let age after reassignment:", age);
// Using const (block-scoped, cannot be reassigned)
const PI = 3.14159;
console.log("const PI:", PI);
// const with objects - the reference is constant, not the value
const user = { name: "Bob" };
user.name = "Charlie"; // This works!
console.log("const user:", user);Comparison: var vs let vs const
Here's a quick comparison of the three declaration keywords:
| Feature | var | let | const |
|---|---|---|---|
| Block Scope | |||
| Function Scope | |||
| Can Be Reassigned | |||
| Can Be Redeclared | |||
| Hoisted | Yes (undefined) | Yes (TDZ) | Yes (TDZ) |
| Must Be Initialized |
Variable Scope
Scope determines where variables are accessible in your code. Understanding scope is crucial for avoiding bugs.
Block Scope (let and const)
Variables declared with let or const are only accessible within the nearest enclosing block ({}).
if (true) {
let blockScoped = "I only exist here";
console.log(blockScoped); // Works
}
console.log(blockScoped); // ReferenceError!Function Scope (var)
Variables declared with var are accessible throughout the entire function, even if declared inside a block.
function example() {
if (true) {
var functionScoped = "I exist in the whole function";
}
console.log(functionScoped); // Works!
}var can cause unexpected bugs. The classic example is using var in a loop with closures. Run this example to see the scope difference in action:
// var is function-scoped
function testVar() {
if (true) {
var x = 10;
}
console.log("var x inside function:", x); // Works! x is 10
}
testVar();
// let and const are block-scoped
function testLet() {
if (true) {
let y = 20;
const z = 30;
console.log("let y inside block:", y);
console.log("const z inside block:", z);
}
// console.log(y); // Would throw ReferenceError!
}
testLet();
// Loop example showing the difference
console.log("\n--- Loop with var ---");
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log("var i:", i), 10);
}
// All print 3 because var is function-scoped
console.log("\n--- Loop with let ---");
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log("let j:", j), 20);
}
// Prints 0, 1, 2 because let is block-scopedHoisting
JavaScript moves variable declarations to the top of their scope before execution. This is called hoisting.
var Hoisting
var declarations are hoisted and initialized with undefined.
console.log(x); // undefined (not an error!)
var x = 5;
console.log(x); // 5let/const Hoisting (Temporal Dead Zone)
let and const are hoisted but NOT initialized. Accessing them before declaration throws a ReferenceError. This period is called the Temporal Dead Zone (TDZ).
console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 5;Best Practices
const for all variables. Only change to let if you discover the value needs to change. let for loop counters, accumulators, or any value that will be updated. var in modern JavaScript. Its scoping behavior causes more bugs than it solves. Common Mistakes
1. Forgetting const with Objects
const prevents reassignment of the variable, not mutation of the value. Objects and arrays declared with const can still be modified. // This is allowed:
const arr = [1, 2, 3];
arr.push(4); // OK - modifying the array
// This is NOT allowed:
arr = [5, 6, 7]; // TypeError!2. Using var in Loops
var in loops with callbacks (like setTimeout) often leads to unexpected results because var is function-scoped. Quick Reference
Cheat Sheet
constDefault choice. Cannot be reassigned.letWhen value will change (counters, accumulators).varAvoid. Legacy code only.Test Your Knowledge
Test Your Knowledge
5 questionsWhich keyword creates a block-scoped variable that can be reassigned?
What happens when you try to reassign a const variable?
What is the "Temporal Dead Zone" (TDZ)?
Can you modify properties of an object declared with const?
Which is the recommended default for declaring variables in modern JavaScript?
Practice Exercises
Challenge 1: Declare Variables
Create three variables using the appropriate keywords: a constant for the maximum number of users, a variable for the current user count, and a constant for the app name.
// Challenge: Declare three variables
// 1. A constant called MAX_USERS set to 100
// 2. A variable called currentUsers set to 0
// 3. A variable called appName set to "MyApp"
// Your code here:
Challenge 2: Fix the Scoping Bug
The code below has a classic scoping bug. Each button should log its own index, but they all log 3. Fix the code by changing one keyword.
// Challenge: Fix the scoping bug
// The code below has a bug related to variable scope.
// Fix it so that each button logs its correct index.
function createButtons() {
const buttons = [];
for (var i = 0; i < 3; i++) {
buttons.push({
label: "Button " + i,
onClick: function() {
console.log("Clicked button", i);
}
});
}
return buttons;
}
const buttons = createButtons();
buttons[0].onClick(); // Should log 0
buttons[1].onClick(); // Should log 1
buttons[2].onClick(); // Should log 2
Frequently Asked Questions
When should I use let vs const?
Use const by default for all variables. Only switch to let when you know the variable needs to be reassigned, such as loop counters or values that accumulate over time.
Can I use var in modern JavaScript?
While var still works, it's not recommended. Its function-scoping and hoisting behavior can lead to subtle bugs. Stick to let and const.
Why can I modify an object declared with const?
const only prevents reassignment of the variable itself, not mutation of the value it holds. The object reference is constant, but the object's properties can still be changed. To make an object truly immutable, use Object.freeze().
What are valid variable names in JavaScript?
Variable names can contain letters, digits, underscores, and dollar signs. They must start with a letter, underscore, or dollar sign (not a digit). They are case-sensitive and cannot be reserved keywords like let, class, or return.
Summary
You've learned the three ways to declare variables in JavaScript and when to use each:
- const - Your default choice. Use for values that won't be reassigned.
- let - Use when you need to reassign a variable (counters, accumulators).
- var - Avoid in modern code. Has confusing scope behavior.
Remember: let and const are block-scoped, while var is function-scoped. This difference is the main reason to prefer the modern keywords.