Yêu cầu thg 8 19, 11:54 CH 47 1 1
  • 47 1 1
0

Variable ENV, Lexical ENV, Closures và Execution context

Chia sẻ
  • 47 1 1

Trong Javascript, nếu làm việc với Closures thường xuyên thì chắc hẳn là ai cũng phải nghe đến 1 trong 2 thuật ngữ như : Lexical ENV và Variable ENV, thậm chí là kể cả Execution Context vì nó khá quan trọng để hiểu được các concept đằng sau hoạt động như thế nào, nhưng tìm các bài viết liên quan đến Lexical ENV thì họ nói không có kĩ và liên quan lắm, chủ yếu ai cũng bảo "Closures thì làm việc với tham chiếu chứ không phải với giá trị của biến" nhưng mà thật sự câu hỏi được đặt ra là liệu "Closures" có dính dáng gì đến "Variable ENV" hay không, hay chỉ thật sự làm việc dựa trên "Lexical ENV" vì "Lexical ENV" nó vẫn tồn tại mặc dù EC đã được pop ra khỏi stack (đồng thời VE cũng bay màu theo), theo em hiểu thì thằng "Lexical ENV" nó chỉ thật sự bay màu khi không còn closures nào refer đến nó, tự khắc Garbage Collector làm việc của nó, nhưng song song với việc đó thì nhiều content cho rằng "Closures" dựa trên "VE", bản chất thì cả 2 "VE" và "LE" đều thuộc "Lexical ENV" nhưng em thấy chỉ có mỗi "LE" là còn tồn tại sau cùng.

1 CÂU TRẢ LỜI


Đã trả lời thg 8 21, 9:05 SA
Đã được chấp nhận
+2

😉 Trước khi trả lời, ta cần hiểu rõ mọi thuật ngữ, mình giải thích đơn giản như sau:

  • Lexical Environment : Ngữ cảnh khi 1 hàm được tạo ra, bao gồm 2 thông tin

    • Environment Record : lưu trữ các biến và hàm được khai báo trong ngữ cảnh
    • Outer Lexical Environment Reference : tham chiếu tới 1 ngữ cảnh Lexical khác ở bên ngoài
  • Variable Environment : Là 1 phần của Lexical Enviroment, nơi lưu trữ các biến được khai báo. (Gần giống Environment Record)

  • Execution Context : bao gồm mọi thứ cần thiết để thực thi mã JavaScript tại một thời điểm nhất định. Một Context bao gồm.

    • Variable Environment : Lưu các biến tạo ra trong hàm hoặc khối lệnh khi thực thi
    • Lexical Environment : Như đã nói ở trên

😀 Nếu bạn đã hiểu các định nghĩa trên, ta hãy tham khảo ví dụ sau :

const funcHandle = () => {
  // "funcHandle Lexical Environment" được tạo ra
  // - Environment Record là a và temp
  // - Outer Lexical Environment Reference : Global Lexical Environment
  let a = 0;

  const temp = () => {
    // "temp Lexical Environment" được tạo ra
    // - Environment Record là c
    // - Outer Lexical Environment Reference : funcHandle Lexical Environment
    let c = 0;

    // +1 cho 2 biến và in ra
    console.log(++a, ++c);
  };
  
  return temp;
};

const run = funcHandle();
run(); // kết quả 1,1
run(); // kết quả 2,1
run(); // kết quả 3,1

Qua ví dụ trên, ta hiểu khi hàm temp được tạo, nó sẽ liên kết với Lexical Enviroment của hàm funcHandle.

Nên khi temp được đại diện bởi run, theo nguyên tắc Garbage Collector sẽ không thể pop Lexical Enviroment của temp (trong đó có biến a) bởi vì nó vẫn còn được tham chiếu tại biến run.

Và khi run được chạy, đồng nghĩa việc chạy temp, Execution Context sẽ được tạo mới, đồng nghĩa Environment Variable cũng phải được làm mới (tạo mới c), chỉ có mỗi funcHandle Lexical Environment vẫn còn được giữ nguyên và tái sử dụng, và đây chính là nguyên tắc hoạt động của Closures khi có thể tái sử dụng lại Lexical Enviroment tại nơi mà nó được tạo ra. 👍️

🚀 Kết luận: Câu trả lời cho câu hỏi của bạn là: Closures làm việc dựa trên Lexical Environment chứ không phải Variable Environment. Bởi Lexical Environment là tiêu điểm khi có thể tái sử dụng được, trong khi Environment Variable luôn được tạo mới mỗi khi Execution Context được tạo và khởi chạy.

👌Happy coding !!!

Chia sẻ
Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí