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

Vòng đời (Lifetime) của biến JavaScript: Global vs Local

Vòng đời của biến JavaScript bắt đầu từ khi được khai báo (declared) và kết thúc tùy thuộc vào phạm vi (scope) của nó.

1. Biến cục bộ (Local Variables)

  • Khai báo: Bên trong một hàm (function) bằng var, let, const.
  • Phạm vi: Chỉ trong hàm đó (Function Scope cho var, Block Scope cho let/const).
  • Tham số hàm cũng là biến cục bộ.
  • Vòng đời: Tạo khi hàm được gọi -> Hủy khi hàm kết thúc thực thi (return hoặc hết code).
  • Mỗi lần gọi hàm -> Tạo bản sao biến cục bộ mới.

2. Biến toàn cục (Global Variables)

  • Khai báo: Bên ngoài mọi hàm, hoặc gán giá trị cho biến chưa khai báo (trong non-strict mode - tránh), hoặc gán vào window/global.
  • Phạm vi: Toàn bộ chương trình (Global Scope). Truy cập được ở mọi nơi.
  • Vòng đời:
    • Trình duyệt: Tồn tại cho đến khi đóng tab/trình duyệt hoặc load trang mới (navigation).
    • Node.js: Tồn tại suốt vòng đời process.
  • Lưu ý: Nếu load trang mới trong cùng tab (không đóng tab), biến global KHÔNG bị xóa (vẫn giữ giá trị) - do bfcache (Back/Forward Cache) hoặc session restore. Khuyến nghị: không phụ thuộc hành vi này.

3. Block Scope (ES6+) - let / const

Biến khai báo bằng let hoặc const trong cặp ngoặc nhọn { } (block: if, for, while, try/catch, hoặc block đơn lẻ):

  • Phạm vi: Chỉ trong block { } đó.
  • Vòng đời: Tạo khi vào block -> Hủy khi ra khỏi block.
  • Temporal Dead Zone (TDZ): Từ đầu block đến dòng khai báo -> Truy cập bị ReferenceError.

Ví dụ minh họa

<!DOCTYPE html>
<html>
<body onload="checkScope()">
<script>
    // 1. Global variable
    var myVar = "global"; 

    function checkScope() {
        // 2. Local variable (Function Scope - var)
        var myVar = "local (var)"; 
        
        // 3. Block Scope (let/const)
        if (true) {
            let blockVar = "block (let)";
            const blockConst = "block (const)";
            console.log("Trong block:", blockVar, blockConst); // OK
        }
        // console.log(blockVar); // ReferenceError: blockVar is not defined
        
        console.log("Trong hàm:", myVar); // "local (var)"
    }
    
    checkScope();
    console.log("Ngoài hàm (global):", myVar); // "global"
</script>
</body>
</html>

Output

Trong block: block (let) block (const)
Trong hàm: local (var)
Ngoài hàm (global): global

So sánh tóm tắt

Loại biếnKhai báoPhạm viVòng đời bắt đầuVòng đời kết thúc
Global (var/let/const ở top-level)Ngoài functionToàn chương trình (window/global)Load scriptĐóng tab / Process exit
Function Local (var)Trong functionFunction ScopeGọi hàmHàm return / kết thúc
Block Local (let/const)Trong { }Block ScopeVào block (TDZ trước khai báo)Ra khỏi block
Function ParameterTrong ( ) hàmFunction ScopeGọi hàmHàm kết thúc

Best Practices

  • Tránh biến toàn cục: Dùng IIFE, Module (ESM), Namespace object.
  • Luôn dùng let/const (ES6+) thay var -> Block scope an toàn, tránh hoisting bug.
  • Hạn chế scope: Khai báo biến ở scope hẹp nhất có thể (block > function > global).
  • Cleanup: Gán null cho object lớn không dùng nữa trong scope dài (global, closure) để GC giải phóng bộ nhớ.

Kết luận: Biến cục bộ (local) sống trong một lần gọi hàm. Biến block (let/const) sống trong block { }. Biến toàn cục (global) sống suốt phiên làm việc trình duyệt/process. Hiểu vòng đời giúp quản lý bộ nhớ, tránh rò rỉ biến, bug khó tìm.