Var, Let, Const in JavaScript
Open this example in our interactive code editor to experiment with it.
Try the EditorIntroduction
Variables are the building blocks of any JavaScript program. They let you store and manipulate data. But JavaScript has three ways to declare variables - var, let, and const - and each behaves differently.
Understanding these differences is crucial for writing clean, bug-free code. In this article, we’ll explore each keyword, their scope rules, hoisting behavior, and when to use which.
Variables
Global Variables
Before we look at var, let, and const, let’s understand global variables. Any variable declared outside of a function (without a keyword, or with var at the top level) becomes a global variable:
// Global variable - accessible everywhere
myGlobal = "I'm global";
function greet() {
console.log(myGlobal); // "I'm global"
}
greet();
console.log(myGlobal); // "I'm global"
Global variables attach to the window object in browsers:
var globalVar = "Hello";
console.log(window.globalVar); // "Hello"
console.log(globalVar); // "Hello"
Warning: Avoid global variables whenever possible. They can lead to naming collisions, make debugging harder, and create unpredictable behavior when multiple scripts modify the same variable.
Var
var is the original way to declare variables in JavaScript (ES5 and earlier). It has function scope - meaning it’s scoped to the nearest function, not the nearest block:
function example() {
var x = 10;
if (true) {
var x = 20; // Same variable! Not a new one.
console.log(x); // 20
}
console.log(x); // 20 - changed by the if block
}
example();
var can also be redeclared without errors:
var name = "Alice";
var name = "Bob"; // No error!
console.log(name); // "Bob"
// This can lead to accidental overwrites
// in large codebases
Var hoisting: Variables declared with var are hoisted to the top of their scope. This means you can reference them before the declaration, but they’ll be undefined:
console.log(hoisted); // undefined (not an error!)
var hoisted = "I'm hoisted";
console.log(hoisted); // "I'm hoisted"
// JavaScript interprets this as:
// var hoisted;
// console.log(hoisted); // undefined
// hoisted = "I'm hoisted";
// console.log(hoisted); // "I'm hoisted"
The fix is simple - always declare variables before using them:
var hoisted = "I'm hoisted";
console.log(hoisted); // "I'm hoisted"
Let
let was introduced in ES6 (ES2015) and is the modern replacement for var. It has block scope - meaning it’s scoped to the nearest curly braces {}:
function example() {
let x = 10;
if (true) {
let x = 20; // Different variable!
console.log(x); // 20
}
console.log(x); // 10 - unchanged
}
example();
let cannot be redeclared in the same scope:
let name = "Alice";
// let name = "Bob"; // SyntaxError: Identifier 'name' has already been declared
But it can be reassigned:
let count = 0;
count = 1; // This is fine
count = 2; // This is fine too
console.log(count); // 2
Let hoisting: let is technically hoisted, but it’s placed in a Temporal Dead Zone (TDZ) from the start of the block until the declaration. Accessing it before the declaration throws an error:
// console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 10;
console.log(x); // 10
This is actually a good thing - it catches bugs that var would silently ignore.
Const
const also has block scope like let, but with one key difference: the binding is constant. You can’t reassign a const variable:
const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable
const name = "Alice";
// name = "Bob"; // TypeError: Assignment to constant variable
However, const does not make objects or arrays immutable. You can still modify their contents:
const user = { name: "Alice", age: 25 };
user.age = 26; // This is fine!
console.log(user); // { name: "Alice", age: 26 }
// But you can't reassign the variable itself:
// user = { name: "Bob" }; // TypeError
const colors = ["red", "green"];
colors.push("blue"); // This is fine!
console.log(colors); // ["red", "green", "blue"]
// But you can't reassign:
// colors = ["yellow"]; // TypeError
If you need a truly immutable object, use Object.freeze():
const frozenUser = Object.freeze({ name: "Alice", age: 25 });
frozenUser.age = 26; // Silently fails (or throws in strict mode)
console.log(frozenUser.age); // 25 - unchanged
Avoiding global scope
Global variables are one of the most common sources of bugs. Here are some tips to avoid them:
- Always use
constorletto declare variables - never rely on implicit global creation - Use modules (ES6
import/export) to encapsulate code - Use IIFEs (Immediately Invoked Function Expressions) in legacy code to create scope
- Enable strict mode (
"use strict") which throws an error when you accidentally create globals - Use a linter like ESLint with the
no-undefandno-varrules - Keep functions small and focused - fewer variables in scope means fewer conflicts
Summary
Here’s a quick reference for when to use each keyword:
- const - Use by default for all variables. It communicates that the binding won’t change and prevents accidental reassignment
- let - Use when you need to reassign a variable (loop counters, accumulators, conditional assignments)
- var - Avoid in modern JavaScript. It has confusing scoping rules and is hoisted in ways that can cause bugs
The general rule is: use const everywhere, and only switch to let when you need to reassign. Never use var.
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function | Block | Block |
| Hoisting | Yes (undefined) | Yes (TDZ) | Yes (TDZ) |
| Redeclaration | Allowed | Not allowed | Not allowed |
| Reassignment | Allowed | Allowed | Not allowed |
| Best for | Legacy code | Mutable values | Everything else |
Closing Notes
Understanding var, let, and const is fundamental to writing good JavaScript. While var was the only option for many years, the introduction of let and const in ES6 gave us better tools for managing variable scope and preventing bugs.
If you’re working with a modern codebase, you should almost never need var. Set up ESLint with the no-var rule and let the tooling enforce this for you.
For more JavaScript fundamentals, check out the MDN documentation on variable declarations.
Ready to level up your coding skills?
Build real projects and grow your portfolio with BigDevSoon.
Start 7-Day Free Trial
Creator of BigDevSoon
Full-stack developer and educator passionate about helping developers build real-world skills through hands-on projects. Creator of BigDevSoon, a vibe coding platform with 21 projects, 100 coding challenges, 40+ practice problems, and Merlin AI.
Related Posts
JavaScript Arrays And How To Avoid Loops
Arrays exist in every programming language. It's a data structure best suited for storing multiple values. And, for doing various operations on these values, often called as a collection.
Boolean And Friends in JavaScript
Conditions, typecasting, logical operators, comparison operators, ternary operator, optional chaining, null-coalescing operator - they are all part of JavaScript.