Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Phạm vi khối (Block Scoping) trong JavaScript

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óaPhạm viHoistingKhái báo lại
varFunctionCó (undefined)Được
letBlockCó (TDZ)Không
constBlockCó (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.