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

Cơ chế phạm vi biến (Variable Scope) trong JavaScript

Scope (phạm vi) xác định nơi biến có thể được truy cập. JavaScript (ES5-) có 2 scope chính: Global và Function (Local). ES6+ thêm Block scope cho let/const.

1. Global Scope

Biến khai báo ngoài mọi hàm. Truy cập được mọi nơi trong chương trình.


var globalVar = "Tôi là global";
function show() { console.log(globalVar); } // Truy cập được

Trong trình duyệt, global variable gắn vào window: window.globalVar.

2. Function Scope (Local Scope - ES5)

Biến khai báo bằng var bên trong hàm. Chỉ truy cập được trong hàm đó.


function demo() {
  var localVar = "Chỉ trong hàm";
  console.log(localVar); // OK
}
demo();
console.log(localVar); // ReferenceError

3. Block Scope (ES6 - let/const)

Biến let/const bị giới hạn trong cặp { } gần nhất (if, for, while, block đơn lẻ).


if (true) {
  let blockVar = "Chỉ trong block";
  const blockConst = "Cũng chỉ trong block";
  var functionScoped = "Ra ngoài hàm được";
}
console.log(blockVar); // ReferenceError
console.log(functionScoped); // OK (var không quan tâm block)

Che giấu biến (Variable Shadowing)

Biến local trùng tên biến global sẽ "che" biến global trong scope local.


var name = "Global";
function greet() {
  var name = "Local"; // Che biến global
  console.log(name); // "Local"
}
greet();
console.log(name); // "Global"

Ví dụ minh họa scope


var myVar = "global";

function checkScope() {
  var myVar = "local"; // Khai báo mới, che biến global
  console.log(myVar); // "local"
}

checkScope(); // "local"
console.log(myVar); // "global"

Hoisting & Scope

  • var: Hoisted lên đầu function scope, khởi tạo = undefined.
  • let/const: Hoisted lên đầu block scope nhưng ở TDZ (Temporal Dead Zone) – truy cập trước khai báo báo lỗi.
  • function declaration: Hoisted hoàn toàn (cả tên lẫn body).

Lexical Scoping (Phạm vi từ vựng)

JS dùng lexical scoping: scope được xác định bởi vị trí viết code (thời gian compile), không phải nơi gọi hàm (runtime).


function outer() {
  var x = 10;
  function inner() {
    console.log(x); // Truy cập x của outer (lexical)
  }
  return inner;
}
var fn = outer();
fn(); // 10 - inner nhớ x của outer (closure)

Best Practice

  • Dùng const mặc định, let khi cần gán lại. Tránh var.
  • Khai báo biến ở đầu scope (block/hàm) để dễ đọc.
  • Hạn chế biến global – dùng module pattern, IIFE, ES Modules.
  • Tận dụng block scope của let/const trong vòng lặp, if.