Hi 🤓 Cảm ơn bạn đã ghé thăm blog này, nếu những bài viết trên blog giúp ích cho bạn. Bạn có thể giúp blog hiển thị quảng cáo bằng cách tạm ngừng ad blocker 😫 và để giúp blog duy trì hoạt động nếu bạn muốn.
Cảm ơn bạn!

Ở bài viết trước thì chúng ta đã tìm hiểu về khái niệm scope trong JavaScript. Trong bài viết lần này, ta sẽ tìm hiểu về lexical scope hay static scope và xem nó có gì thú vị nhé 😁.

Lexical scope trong JavaScript là gì?

Trước tiên, mình xin sử dụng lại ví dụ từ bài viết hôm trước. Bạn nào chưa hiểu về scope có thể đọc bài viết này: Scope trong JavaScript là gì?.

function hamOBenNgoai() {
  // scope
  let text = 'outside';
  function hamOBenTrong() {
    // scope
    console.log(text); // outside
  }
  hamOBenTrong();
}
hamOBenNgoai();

Một câu hỏi đặt ra là: "Làm sao JavaScript có thể hiểu được biến text trong hamOBenTrong() là biến từ hamOBenNgoai()?".

JavaScript có một cơ chế xác định scope có tên là lexical scope hay static scope.

Lexical scope là nơi mà một biểu thức được tạo ra.

Lexical scope hiểu đơn giản là một biến được khai báo bên ngoài một hàm, có thể truy xuất được khi sử dụng biến này bên trong một hàm khác. Điều ngược lại là không đúng. Các biến được khai báo bên trong một hàm sẽ không thể sử dụng được bên ngoài hàm đó.

Cùng xem một ví dụ để hiểu hơn về lexical scope nhé:

const user = 'Hung';
function hamBenNgoai() {
  const phone = 123123;
  console.log(user); // Hung
  function hamBenTrong() {
    const old = 22;
    console.log(user, phone); // Hung, 123123
    function hamBenTrongCung() {
      console.log(user, phone, old); // Hung, 123123, 22
    }
    hamBenTrongCung();
  }
  hamBenTrong();
}
hamBenNgoai();

Ở ví dụ trên ta khai báo một biến userglobal scope. Ta thực thi (invoked) hàm hamBenNgoai(). Trong hàm này ta sử dụng biến user từ global scope 👌. Vậy câu hỏi đặt ra là lexical scope của user thuộc phạm vi toàn cục (global scope) hay scope của hamBenNgoai()?

lexical scope có nghĩa là chúng ta đang xét về không gian định nghĩa chứ không phải là nơi mà ta gọi user. Do đó, lexical scope của userglobal scope vì ta đã khai báo userglobal environment ^^.

Cùng tiếp tục theo dõi ví dụ trên, ta thấy lexical scope của hamBenTrongCung() bao gồm cả scope của hamBenTrong(), hamBenNgoai() và global scope. Ta có thế truy cập các biến khi ở trong lexical scope của biến đó. Chính vì thế trong hamBenTrong() ta có thể sử dụng biến user, phone, old.

lexical scope của hamBenTrong() bao gồm scope của hamBenNgoai() và global scope. Do đó ta có thể sử dụng biến user, phone, vì ta đang sử dụng các biến này trong lexical scope của chúng.

lexical scope của hamBenNgoai() là global scope. Nên ta chỉ có thể sử dụng được biến user ở ví dụ trên 😁.

Tiếp tục một ví dụ nữa để các bạn hiểu rõ hơn nhé ^^. Ví dụ này mình đã lấy từ bài trước:

function sinhVienCNTT() {
  let tenSinhVien = 'Trang';
  let mssv = 1851120000;
}

function dangKyMonHoc(){
  console.log(mssv);
}
sinhVienCNTT();
dangKyMonHoc(); // mssv is not defined

Ở ví dụ trên, ta sẽ gặp một lỗi đó là mssv is not defined. Như chúng ta đã tìm hiểu về lexical scope đó là ta chỉ có thể sử dụng được biến mssv khi ta dùng biến đó ở trong lexical scope của nó.

Ta khai báo biến mssv trong sinhVienCNTT() do đó lexical scope của mssv là scope sinhVienCNTT(). Đối với dangKyMonHoc(), lexical scope của nó là global scope. Chính vì hai lexical scope này khác nhau nên ta không thể sử dụng biến mssv trong dangKyMonHoc() được 😁😊.

Kết luận

Chúng ta đã cùng nhau tìm hiểu về lexical scope trong JavaScript rồi. Hy vọng bài viết sẽ giúp các bạn hiểu về lexical scope hơn ^^.

Chúc các bạn học tốt.

Có thể bạn thích ⚡
homiedev
About Me

Hi, I'm @devnav. Một người thích chia sẻ kiến thức, đặc biệt là về Frontend 🚀. Trang web này được tạo ra nhằm giúp các bạn học Frontend hiệu quả hơn 🎉😄.

Chúc các bạn tìm được kiến thức hữu ích trong blog này 😁😁.