
Introduction
For many years, var was the only way to declare a variable in JavaScript. With the introduction of ES6 (ECMAScript 2015), two new keywords, let and const, were added, providing more control over variable scope and behavior. Understanding the differences between these three is crucial for writing modern, maintainable, and bug-free JavaScript.
This guide will compare var, let, and const based on their scope, hoisting, and reassignment rules.
1. Scope
Scope determines where a variable is accessible in your code.
var: Function Scope
Variables declared with var are function-scoped. This means they are only accessible within the function they are declared in. If declared outside any function, they have a global scope.
function myFunction() {
if (true) {
var myVar = "Hello from var";
}
console.log(myVar); // "Hello from var" - Accessible here
}
myFunction();
// console.log(myVar); // ReferenceError: myVar is not defined - Not accessible here
Notice that myVar is accessible outside the if block. This is because var does not respect block scope ({...}), which can lead to unexpected behavior.
let and const: Block Scope
Variables declared with let and const are block-scoped. They are only accessible within the block (i.e., inside the curly braces {...}) in which they are defined.
function anotherFunction() {
if (true) {
let myLet = "Hello from let";
const myConst = "Hello from const";
console.log(myLet); // Accessible
console.log(myConst); // Accessible
}
// console.log(myLet); // ReferenceError: myLet is not defined
// console.log(myConst); // ReferenceError: myConst is not defined
}
anotherFunction();
This is much more intuitive and similar to how variables work in many other programming languages. It helps prevent bugs by limiting the variableโs lifecycle to the block where itโs needed.
2. Hoisting
Hoisting is JavaScriptโs behavior of moving declarations to the top of their scope before code execution.
var: Hoisted and Initialized
var variables are hoisted to the top of their scope and are initialized with a value of undefined.
console.log(hoistedVar); // undefined (No error)
var hoistedVar = "I am hoisted";
console.log(hoistedVar); // "I am hoisted"
This means you can access a var variable before itโs declared without getting an error, though its value will be undefined.
let and const: Hoisted but Not Initialized
let and const variables are also hoisted, but they are not initialized. Accessing them before the declaration results in a ReferenceError. The period from the start of the block to the declaration is called the Temporal Dead Zone (TDZ).
// console.log(hoistedLet); // ReferenceError: Cannot access 'hoistedLet' before initialization
let hoistedLet = "I am hoisted too";
// console.log(hoistedConst); // ReferenceError: Cannot access 'hoistedConst' before initialization
const hoistedConst = "So am I";
This behavior prevents you from accidentally using a variable before its value is assigned, making the code more robust.
3. Reassignment
This is the primary difference between let and const.
var and let: Can be Reassigned
Variables declared with var or let can be updated or reassigned.
var myVarVariable = "First value";
myVarVariable = "New value"; // Allowed
let myLetVariable = "First value";
myLetVariable = "New value"; // Allowed
const: Cannot be Reassigned
Variables declared with const (short for constant) must be initialized at the time of declaration and cannot be reassigned a new value.
const myConstVariable = "This value is constant";
// myConstVariable = "Trying to change"; // TypeError: Assignment to constant variable.
Important Note for Objects and Arrays:
When you declare an object or array with const, it means the reference to that object/array is constant, not its content. You can still modify the properties of the object or the elements of the array.
const myObj = { name: "Alice" };
myObj.name = "Bob"; // This is allowed!
console.log(myObj.name); // "Bob"
const myArray = [1, 2, 3];
myArray.push(4); // This is also allowed!
console.log(myArray); // [1, 2, 3, 4]
// But you cannot reassign the variable itself
// myObj = { name: "Charlie" }; // TypeError
// myArray = [5, 6]; // TypeError
Summary and Best Practices
| Keyword | Scope | Hoisting | Reassignment | Redeclaration (in same scope) |
|---|---|---|---|---|
var |
Function | Hoisted and initialized to undefined |
Yes | Yes |
let |
Block | Hoisted, but not initialized (TDZ) | Yes | No |
const |
Block | Hoisted, but not initialized (TDZ) | No | No |
Here are the modern JavaScript best practices for variable declaration:
- Use
constby default: This makes your code more predictable by preventing accidental reassignments. It signals that the variableโs identifier will not be reassigned. - Use
letonly when you know you need to reassign the variable: This is typically for loop counters or variables that need to be updated within a block. - Avoid using
var: There is generally no reason to usevarin modern JavaScript (ES6+). Its function-scoping and hoisting behavior can lead to bugs thatletandconstwere designed to prevent.
By following these rules, you will write clearer, more reliable, and easier-to-debug JavaScript code.
Professional Depth Check
For JavaScript Variables: The Difference Between var, let, and const, the practical standard is not whether the reader can repeat one instruction once. Treat the topic as a reproducible debugging procedure: verify runtime environment, exact error boundary, minimal reproduction, and rollback path before drawing a conclusion. The result should be written as a small decision record, because future readers need to know which fact was observed, which assumption was used, and which condition would change the answer.
Evidence That Makes the Guidance Reliable
Use objective evidence before changing a workflow. Good evidence includes full command output, version numbers, changed files, and expected versus actual behavior. If two pieces of evidence conflict, keep the conflict visible instead of smoothing it over. For example, a successful quick fix is still weak evidence if the same input, account, dependency, or device state has not been tested again. A durable article should help the reader distinguish a confirmed fix from a plausible fix.
Review Table
| Review Item | What To Confirm | Why It Matters |
|---|---|---|
| Scope | The exact case covered by this article | Prevents over-applying the advice |
| Baseline | The state before any change | Makes rollback and comparison possible |
| Change | The smallest action taken | Reduces hidden side effects |
| Result | The observed output after the change | Separates evidence from expectation |
| Recheck | When to revisit the conclusion | Keeps the post accurate over time |
Related Reading
Continue with these related posts from the same topic area.
Leave a comment