Phạm vi khối (Block Scope) là vùng code nằm giữa cặp dấu ngoặc nhọn { } (ví dụ: trong if, for, while, switch hoặc khối độc lập). Biến khai báo với let và const (ES2015+) được giới hạn trong khối này — không thể truy cập từ bên ngoài.
Đặc điểm chính
let&const: Block-scoped (phạm vi khối).var: Function-scoped (phạm vi hàm) — bỏ qua khối.- Biến block-scoped không bị hoisting ra ngoài khối (tạm thời "Temporal Dead Zone").
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>Block Scoping</title>
<style>
body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; max-width: 600px; margin: 2rem auto; padding: 0 1rem; }
.result { font-size: 1.1rem; font-weight: 500; color: green; white-space: pre-line; }
button { padding: 0.5rem 1rem; background: #fd7e14; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; }
button:hover { background: #e8690b; }
</style>
</head>
<body>
<h1>Phạm vi khối (Block Scoping) trong JavaScript</h1>
<div class="result" id="resultEl"></div>
<button id="btn">KIỂM TRA PHẠM VI</button>
<p>Nhấn nút để xem biến 'b' (ngoài khối) và 'a' (trong khối)</p>
<script>
const resultEl = document.getElementById('resultEl');
document.getElementById('btn').addEventListener('click', () => {
let b = 44; // Biến trong khối hàm callback
{ // Khối lồng nhau (nested block)
let a = 22; // Chỉ tồn tại trong khối này
}
// Truy cập b - OK
resultEl.textContent = `Truy cập trong khối của nó: b = ${b}\n`;
// Truy cập a - LỖI
try {
a; // ReferenceError
} catch (err) {
resultEl.textContent += `Truy cập ngoài khối: ${err.name} - ${err.message}`;
}
});
</script>
</body>
</html>
Kết quả
Kết quả hiển thị:
Truy cập trong khối của nó: b = 44
Truy cập ngoài khối: ReferenceError - a is not defined
So sánh: var vs let/const
function varExample() {
if (true) {
var x = 10; // Function-scoped
}
console.log(x); // 10 - TRUY CẬP ĐƯỢC (var bỏ qua khối if)
}
function letExample() {
if (true) {
let y = 20; // Block-scoped
}
console.log(y); // ReferenceError - KHÔNG TRUY CẬP ĐƯỢC
}
Ứng dụng thực tế
1. Vòng lặp for - tránh closure trap
// Với var - in ra 5 lần số 5
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100); // 5,5,5,5,5
}
// Với let - in ra 0,1,2,3,4 (mỗi lần lặp tạo scope mới)
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100); // 0,1,2,3,4
}
2. Khối độc lập để cô lập biến tạm
{
const temp = fetchData();
process(temp);
} // temp bị giải phóng/hủy sau khối này
Tóm tắt
| Từ khóa | Phạm vi | Hoisting | Khái báo lại |
|---|---|---|---|
var | Function | Có (undefined) | Được |
let | Block | Có (TDZ) | Không |
const | Block | Có (TDZ) | Không |
Khuyến nghị: Mặc định dùng const, chỉ dùng let khi cần gán lại. Tránh var trong code hiện đại.