Nắm vững JavaScript: Khám phá Scope, Hoisting và Closures

05 tháng 4, 2026·3 phút đọc

Scope xác định phạm vi truy cập của biến, Hoisting là cơ chế chuẩn bị bộ nhớ trước khi thực thi, và Closures cho phép hàm "nhớ" dữ liệu từ môi trường bên ngoài. Hiểu rõ những nguyên lý này giúp lập trình viên viết code JavaScript sạch sẽ, dễ bảo trì và tối ưu hóa hiệu năng ứng dụng.

Nắm vững JavaScript: Khám phá Scope, Hoisting và Closures

Scope là gì? (Phạm vi)

Scope trong JavaScript quyết định đâu là "biên giới" mà ở đó một biến có thể được truy cập. Nghe có vẻ đơn giản, nhưng Scope là nền tảng quan trọng để ngăn chặn xung đột biến và quản lý bộ nhớ hiệu quả trong ứng dụng.

Có 4 loại Scope chính:

  • Global Scope: Biến có thể truy cập từ bất cứ đâu trong mã nguồn.
  • Function Scope: Biến chỉ khả dụng bên trong hàm chứa nó.
  • Block Scope: Biến chỉ khả dụng trong khối lệnh {} (thường sử dụng với letconst).
  • Lexical Scope: Được xác định bởi cấu trúc mã nguồn viết ra.

Ví dụ thực tế về Scope:

let person = [1, 2, 3, 4, 5]; // Biến toàn cục

function total(num1, num2) {
    const result = num1 + num2; // Biến trong phạm vi hàm

    if (true) {
        var result1 = num1 * num2; // var có phạm vi hàm
    }

    console.log(result1); // Có thể truy cập
    console.log(person);  // Có thể truy cập từ hàm
}

total(10, 20);
console.log(result); // ❌ Lỗi: result không tồn tại bên ngoài hàm

Hoisting là gì?

Hoisting là hành vi đặc thù của JavaScript, nơi các khai báo biến và hàm được "di chuyển" lên đầu bộ nhớ ngay trước khi mã thực thi. Điều này có nghĩa là bạn có thể sử dụng một biến hoặc hàm trước khi khai báo nó trong mã nguồn, miễn là bạn không cố tình truy cập vào vùng Temporal Dead Zone.

Tuy nhiên, cách xử lý khác nhau tùy thuộc từ khóa khai báo:

  • var: Được đẩy lên và khởi tạo với giá trị undefined.
  • let/const: Được đẩy lên nhưng chưa được khởi tạo (nằm trong vùng Temporal Dead Zone - TDZ), dẫn đến lỗi ReferenceError nếu truy cập trước khi gán giá trị.
  • Function declarations: Được đẩy lên hoàn toàn.

Ví dụ minh họa:

console.log(a); // undefined (do var được hoisting)
var a = 10;

// Giống như JS hiểu thành:
var a;
console.log(a);
a = 10;

// Với let/const:
console.log(b); // ❌ ReferenceError
let b = 10;

Closures (Khép kín) là gì?

Closures xảy ra khi một hàm bên trong "nhớ" và truy cập các biến từ phạm vi bên ngoài (hàm cha), ngay cả khi hàm bên ngoài đã kết thúc thực thi. Điều này tạo ra một mối quan hệ mật thiết giữa hàm và môi trường xung quanh nó, cho phép hàm lưu giữ trạng thái giữa các lần gọi.

Tại sao Closures lại quan trọng?

  • Giữ dữ liệu riêng tư (Private data).
  • Duy trì trạng thái (State management) giữa các lần gọi hàm.
  • Rất phổ biến trong các framework như React (Hooks) và các kỹ thuật thiết kế module.

Ví dụ sử dụng Closures:

function total() {
    let counter = 0; // Biến riêng tư trong hàm total

    return function() {
        counter++; // Hàm con truy cập biến của hàm cha
        console.log(counter);
    };
}

const result1 = total();
result1(); // 1
result1(); // 2

const result2 = total();
result2(); // 1
result1(); // 3

Kết luận

Ba khái niệm Scope, HoistingClosures không chỉ là lý thuyết khô khan mà là động lực ngầm cho mọi hành vi của JavaScript. Khi bạn hiểu rõ Scope để phân chia vùng nhớ, hiểu rõ Hoisting để tránh lỗi chưa khởi tạo, và hiểu rõ Closures để tạo ra các hàm linh hoạt, bạn sẽ chuyển từ việc viết code "may rủi" sang lập trình chuyên nghiệp và dễ bảo trì hơn rất nhiều.

Bài viết được tổng hợp và biên soạn bằng AI từ các nguồn tin tức công nghệ. Nội dung mang tính tham khảo. Xem bài gốc ↗