When you first learn JavaScript, one of the things that often causes confusion is that there are three ways to declare a variable: var, let, and const. All three look similar but behave very differently. Understanding the differences is important so your code doesn't produce hard-to-track bugs.
A Brief History
Before ES6 (ECMAScript 2015), the only way to declare a variable in JavaScript was with var. ES6 then introduced let and const to address some of the weaknesses of var. Today, using var is no longer recommended in modern code.
Scope Differences
The most fundamental difference is scope (the variable's range of visibility).
var has function scope — the variable is limited to the function, but can be accessed outside of blocks such as if or for:
function contohVar() {
if (true) {
var nama = 'Budi'; // var doesn't care about {} blocks
}
console.log(nama); // 'Budi' — accessible! (no error)
}
function contohLet() {
if (true) {
let nama = 'Budi'; // let only exists inside the {} block
}
console.log(nama); // ReferenceError: nama is not defined
}
let and const have block scope — the variable only exists inside the {} block where it was declared. This is much safer and more predictable.
Hoisting
All three keywords undergo hoisting (being moved to the top by the JavaScript engine), but in different ways:
// With var — no error, the result is undefined
console.log(angka); // undefined (not an error)
var angka = 10;
console.log(angka); // 10
// With let — error!
console.log(nilai); // ReferenceError: Cannot access 'nilai' before initialization
let nilai = 20;
var is hoisted and immediately initialized with the value undefined. Meanwhile, let and const are hoisted but not initialized — they enter the "Temporal Dead Zone" until the line where they are declared is executed. This behavior of var is often a source of confusing bugs.
Re-declaration and Re-assignment
Another important difference is the ability to re-declare and change values:
// var — can be re-declared
var kota = 'Jakarta';
var kota = 'Bandung'; // No error — kota is now 'Bandung'
// let — the value can be changed, but it CANNOT be re-declared
let kota2 = 'Jakarta';
kota2 = 'Bandung'; // OK — the value changes
let kota2 = 'Surabaya'; // SyntaxError: Identifier 'kota2' has already been declared
// const — the value CANNOT be changed AND it cannot be re-declared
const negara = 'Indonesia';
negara = 'Malaysia'; // TypeError: Assignment to constant variable
const Doesn't Mean the Value Can Never Change at All
It's important to understand that const means the binding cannot be changed, not the value inside it. For objects and arrays, their properties can still be modified:
const user = {
nama: 'Andi',
umur: 25
};
user.umur = 26; // OK! Object properties can be changed
user.kota = 'Yogyakarta'; // OK! New properties can be added
console.log(user); // { nama: 'Andi', umur: 26, kota: 'Yogyakarta' }
user = {}; // TypeError! You can't replace the object reference
// The same applies to arrays
const angka = [1, 2, 3];
angka.push(4); // OK!
angka = [5, 6]; // TypeError!
When Should You Use Each One?
- const — Use this as the default for all variables whose value won't be reassigned. It makes your code safer and easier to understand.
- let — Use this when you need to change a variable's value, for example a counter in a loop or a variable whose value depends on a condition.
- var — Best to avoid in modern code. You'll only encounter it in legacy code.
// Examples of proper usage
const MAX_RETRY = 3; // fixed value, use const
const baseUrl = 'https://api.example.com'; // fixed value, use const
let hitungCoba = 0; // will change, use let
let isLoggedIn = false; // will change, use let
for (let i = 0; i < 5; i++) { // i changes each iteration, use let
console.log(i);
}
Comparison Summary
- Scope:
var= function scope |let&const= block scope - Hoisting:
var= initialized as undefined |let&const= Temporal Dead Zone - Re-declaration:
var= allowed |let&const= not allowed - Re-assignment:
var&let= allowed |const= not allowed
Conclusion
Use const as your primary choice, then switch to let only if the variable's value needs to change. Avoid var because its unintuitive scope and hoisting behavior can cause hard-to-track bugs. With this habit, your JavaScript code will be cleaner, safer, and easier for others to understand.