Understanding JavaScript Variable Declarations: var, let, const


Hey there, fellow JavaScript enthusiasts!
Today, we're diving into a fundamental aspect of modern JavaScript: variable declarations. If you've ever felt a bit hazy about var, let and const what they are, how they differ, and when to use each; you're in the right place! We'll break down their behavior with clear examples and explore how they act in various scenarios.
Let's unravel the mystery behind these!
Unpacking var, let, and const: A Closer Look
For a long time, var was the go-to for declaring variables in JavaScript. But with ES6 (ECMAScript 2015), let and const stepped onto the scene, giving us more control and helping us write cleaner, less error-prone code.
Var: The Traditional Variable
var has been around forever, and while it still works, it comes with some quirks that can lead to unexpected behavior, especially in larger codebases.
What var does:
Function-Scoped: Variables declared with var live within the nearest function. If you declare one outside any function, it becomes global. This means they don't care about blocks like if statements or for loops.
function sayHello() { if (true) { var greeting = "Hi there!"; } console.log(greeting); // Output: "Hi there!" (greeting is available outside the if block) } sayHello(); console.log(greeting); // Output: ReferenceError: greeting is not defined (can't access outside the function)
Hoisting: Hoisting is a concept which enables us to extract values of variables and functions even before initializing/assigning value without getting an error. This is happening due to the 1st phase (memory creation phase) of the Execution Context. For var, during this phase, the variable is set up in memory and given an initial value of undefined.
console.log(note); // Output: undefined (declaration is hoisted, but not the assignment) var note= "var is Hoisting"; console.log(note); // Output: "var is Hoisting"
Re-declaration Allowed: You can declare a var variable multiple times in the same scope without any fuss.
var value = 10; console.log(value); // Output: 10 var value = 30; // No problem, 'value' is simply re-declared console.log(value); // Output: 30
Things to Watch Out For with var:
Unexpected Scope: Because var isn't block-scoped, variables can "escape" blocks where you'd expect them to stay, potentially causing clashes.
Hoisting Surprises: While hoisting can seem handy, it can make code harder to follow if variables are used before their visible declaration.
let: The flexible, Block-Scoped Variable
let arrived to fix many of var 's quirks. It provides more predictable and intuitive scoping.
What let Does:
Block-Scoped: Variables declared with let are confined to the closest block (anything within {}). Think if statements, for loops, or just standalone code blocks.
if (true) { let region = "Asia"; console.log(region); // Output: "Asia" } console.log(region); // Output: ReferenceError: region is not defined (can't access outside the if block)
Hoisting (with a Twist): let declarations are also hoisted, but they don't get initialized. They enter a "Temporal Dead Zone" (TDZ) from the block's start until their actual declaration. Trying to use a let variable in its TDZ will throw a ReferenceError.
console.log(continent); // Output: ReferenceError: Cannot access 'continent' before initialization let continent = "Europe"; console.log(continent); // Output: "Europe"
No Re-declaration: You can't declare a let variable again within the same scope.
let count = 5; console.log(count); // Output: 5 let count = 10; // Output: SyntaxError: Identifier 'count' has already been declared
When to Use let:
Loop Variables: let is perfect for loop counters. It ensures the variable is unique to each loop iteration, preventing common problems seen with var in asynchronous loops.
Temporary Variables: Use let for variables that might need to be reassigned later but should stay within a specific block of code.
const: The (mostly) unchangeable constant
const is also block-scoped and, as its name suggests, is for declaring constants. But it's important to understand what "constant" truly means here.
What const Does:
Block-Scoped: Just like let and const variables are block-scoped.
if (true) { const isAdmin = true; console.log(isAdmin); // Output: true } console.log(isAdmin); // Output: ReferenceError: isAdmin is not defined
Hoisting (with a Twist): const declarations also experience hoisting and the Temporal Dead Zone, just like let.
No Re-declaration: You can't declare a const variable again in the same scope.
const VERSION = "1.0.0"; const VERSION = "1.0.1"; // Output: SyntaxError: Identifier 'VERSION' has already been declared
Must Be Initialized: A const variable must be given a value when you declare it. You can't declare it without assigning something to it.
// Must Be Initialized const userName; // Output: SyntaxError: Missing initializer in const declaration
Immutable Binding: The binding of a const variable is set in stone. This means you can't assign a new value to the const variable after its initial declaration.
// Immutable Binding for primitive values const score = 100; score = 150; // Output: TypeError: Assignment to constant variable. // Immutable Binding vs. Mutable Content (for objects/arrays) const userProfile = { name: "John Doe", age: 30 }; console.log(userProfile); // Output: { name: 'John Doe', age: 30 } userProfile.age = 31; // This is totally fine! We're changing a property of the object. console.log(userProfile); // Output: { name: 'John Doe', age: 31 } userProfile = { status: "active" }; // This is NOT allowed! Trying to assign a new object to 'userProfile'. // Output: TypeError: Assignment to constant variable.
Crucial for Objects/Arrays: While the variable itself can't be reassigned to something new, the contents of an object or array declared with const can still be changed. You just can't make the variable point to a completely different object or array.
const favoriteColors = ["red", "blue"]; favoriteColors.push("green"); // Allowed! We're adding an item to the array. console.log(favoriteColors); // Output: ['red', 'blue', 'green'] favoriteColors = ["yellow", "purple"]; // Not allowed! Trying to assign a new array to 'favoriteColors'. // Output: TypeError: Assignment to constant variable.
When to use const:
True Constants: Use const for values that should never change throughout your program's life (like mathematical constants or fixed configuration settings).
Readability and Intent: Using const clearly signals that a variable's reference won't be reassigned. This makes your code easier to read and understand.
Objects and Arrays: Remember that const only prevents the variable itself from being reassigned, not the contents of the object or array it points to.
Picking the Right Declaration: A Simple Rule
Now that you've got the understanding, here's a straightforward guide for modern JavaScript:
Start with const : Always try to declare your variables with const first. If you later realize you need to reassign the variable, then...
Switch to let : If reassignment becomes necessary, change const to let.
Avoid using var : In most new JavaScript code, there's rarely a good reason to use var. Sticking with let and var will give you better control, predictability, and fewer potential bugs.
Wrapping Up
Mastering var, let, and const is fundamental to writing robust, maintainable, and modern JavaScript code. By understanding their distinct behaviors, especially how they handle scope, hoisting, and immutability; you can make smart choices about variable declarations and avoid common pitfalls.
Happy coding! If you have any questions or suggestions you'd like to explore further, feel free to drop a comment below.
See you in the next blog. Please don’t forget to follow me:
Subscribe to my newsletter
Read articles from Nitin Saini directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Nitin Saini
Nitin Saini
A Full Stack Web Developer, possessing a strong command of React.js, Node.js, Express.js, MongoDB, and AWS, alongside Next.js, Redux, and modern JavaScript (ES6+)