Ba từ khóa khai báo biến: var, let, const
JavaScript hiện đại có 3 cách khai báo biến, mỗi cái có đặc điểm riêng về phạm vi (scope), hoisting, và khả năng gán lại.
| Từ khóa | Phạm vi | Hoisting | Gán lại | Khởi tạo bắt buộc | Năm |
|---|---|---|---|---|---|
| var | Function | Có (khởi tạo = undefined) | ✓ | Không | 1995 |
| let | Block | Có (TDZ - không khởi tạo) | ✓ | Không | 2015 |
| const | Block | Có (TDZ - không khởi tạo) | ✗ | Có | 2015 |
Ví dụ minh họa
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Khai báo biến</title>
<style>
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; }
.result { font-size: 18px; font-weight: 500; color: blueviolet; font-family: monospace; }
button { padding: 8px 16px; cursor: pointer; }
</style>
</head>
<body>
<h1>Các cách khai báo biến trong JavaScript</h1>
<div class="result"></div>
<button class="btn-demo">KHAI BÁO VÀ TRUY CẬP</button>
<h3>Nhấn nút để khai báo var, let, const và truy cập</h3>
<script>
const btn = document.querySelector(".btn-demo");
const resEle = document.querySelector(".result");
btn.addEventListener("click", () => {
// var: hoisted, khởi tạo = undefined
resEle.innerHTML = "a (var) = " + a + "<br>";
// let: hoisted nhưng TDZ, chưa khởi tạo
try {
resEle.innerHTML += "b (let) = " + b + "<br>";
} catch (err) {
resEle.innerHTML += "b (let) = " + err.message + "<br>";
}
// const: hoisted nhưng TDZ, chưa khởi tạo
try {
resEle.innerHTML += "c (const) = " + c + "<br>";
} catch (err) {
resEle.innerHTML += "c (const) = " + err.message + "<br>";
}
// Khai báo SAU khi truy cập (hoisting)
var a = 22;
let b = 44;
const c = 99;
// Thử gán lại const
try {
c = 44;
} catch (err) {
resEle.innerHTML += "Gán lại const: " + err.message + "<br>";
}
});
</script>
</body>
</html>
Chi tiết từng từ khóa
var - Function Scoped
function demo() {
if (true) {
var x = 10;
}
console.log(x); // 10 - var 무시 block {}
}
// Hoisting: var được kéo lên đầu function và khởi tạo = undefined
console.log(a); // undefined (không lỗi)
var a = 5;
let - Block Scoped, có thể gán lại
{
let x = 10;
x = 20; // OK
}
console.log(x); // ReferenceError
// Vòng lặp - let tạo binding mới mỗi lần lặp
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 0, 1, 2
}
const - Block Scoped, không gán lại được
const PI = 3.14159;
// PI = 3; // TypeError
// Nhưng object/array const VẪN có thể thay đổi nội dung
const user = { name: 'A' };
user.name = 'B'; // OK
user.age = 25; // OK
const arr = [1, 2];
arr.push(3); // OK
// arr = []; // TypeError
Best Practice hiện đại
- Mặc định:
const- cho tất cả khai báo. - Cần gán lại:
let- counter, accumulator, swap. - Tránh
var- trừ khi maintain code cũ.