The difference between var, let, and const
May 12, 2026
JavaScript gives you three ways to declare a variable: var, let, and const. They look similar, but they behave differently in three areas: scope, hoisting, and whether you can reassign them. Understanding those differences helps you avoid a whole class of confusing bugs.
var
This is the original keyword. A var is function-scoped, which means it is visible everywhere inside the function it was declared in, even outside the block it appears in. It is also hoisted and set to undefined before the code runs, so using it early does not throw an error. You can redeclare and reassign it freely.
function test() {
if (true) {
var x = 5;
}
console.log(x); // 5 - still visible outside the if block
}
let
A let is block-scoped. It only exists inside the nearest set of curly braces, whether that is a function, an if block, or a loop. It is hoisted too, but you cannot use it before its declaration line runs. That gap is called the temporal dead zone, and reaching into it throws an error. You can reassign a let, but you cannot redeclare it in the same scope.
if (true) {
let y = 5;
}
console.log(y); // ReferenceError - y only lived inside the block
const
A const behaves like let for scope and the temporal dead zone, but it cannot be reassigned and must be given a value when you declare it. One thing that trips people up: const makes the binding constant, not the value. If a const holds an object or array, you can still change what is inside it.
const user = { name: "Will" };
user.name = "William"; // allowed - we changed a property
user = {}; // TypeError - we tried to reassign the binding
Which should you use
A good default is to reach for const first, since most variables never need to be reassigned and const makes that intent clear. Use let when you genuinely need to reassign, like a counter in a loop. Avoid var in new code, because its function scoping and silent hoisting cause bugs that the block-scoped keywords simply prevent.