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
const
by default: This makes your code more predictable by preventing accidental reassignments. It signals that the variableโs identifier will not be reassigned. - Use
let
only 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 usevar
in modern JavaScript (ES6+). Its function-scoping and hoisting behavior can lead to bugs thatlet
andconst
were designed to prevent.
By following these rules, you will write clearer, more reliable, and easier-to-debug JavaScript code.
Leave a comment