Lesson 1.1.4 — Creation Phase vs Execution Phase
0. Metadata (Thông tin bài học)
| Trường | Giá trị |
|---|---|
| Stage | 1 — JavaScript Execution Model |
| Module | 1.1 — Execution Context |
| Lesson | 1.1.4 — Creation Phase vs Execution Phase |
| Competency | C02 — JavaScript Runtime |
| Depth | L2–L3 (Explain → Use) |
| Prerequisites | Lesson 1.1.1–1.1.3 — Execution Context, Global FEC, Function FEC |
| Thời gian ước tính | 35–45 phút |
1. Why This Exists (Vì sao cần học)
Bạn đã biết Execution Context là container nơi code chạy. Bạn cũng biết mỗi lần gọi hàm tạo ra một Function Execution Context mới.
Nhưng câu hỏi này sẽ làm bạn dừng lại:
console.log(greet);
function greet() {
return "hello";
}Nếu bạn nghĩ engine đọc code từ trên xuống, dòng đầu tiên chạy trước, thì greet ở dòng 1 phải là undefined hoặc lỗi. Nhưng khi chạy:
[Function: greet]greet đã tồn tại trước khi dòng định nghĩa function greet() được thực thi.
Tại sao?
Vì mỗi Execution Context không chạy code ngay lập tức. Engine chuẩn bị trước, rồi mới chạy sau.
Nếu không hiểu hai phase này, bạn sẽ:
- Không hiểu tại sao
functioncó thể gọi trước khi định nghĩa - Không hiểu tại sao
var xtồn tại nhưng lại làundefinedtrước dòng khai báo - Không thể học Hoisting (Module 1.3) vì hoisting chính là hệ quả của Creation Phase
- Không thể debug lỗi
ReferenceErrorvsundefinedmột cách có hệ thống
2. Prerequisites (Yêu cầu đầu vào)
Bạn cần đã học:
- Lesson 1.1.1 — Execution Context là gì?
- Lesson 1.1.2 — Global Execution Context
- Lesson 1.1.3 — Function Execution Context
- Biết
var,let,const,functiondeclaration
3. Learning Objectives (Mục tiêu học tập)
Sau bài này, bạn có thể:
- Giải thích tại sao mỗi Execution Context có hai phase: Creation và Execution
- Phân biệt những gì xảy ra trong Creation Phase (setup) và Execution Phase (run)
- Dự đoán giá trị của biến/hàm tại một dòng code cụ thể dựa trên phase hiện tại
- Trace luồng từ Creation Phase sang Execution Phase trong một đoạn code đơn giản
4. Mental Model (Mô hình tư duy)
Mỗi Execution Context = Chuẩn bị trước, chạy sau
Khi engine tạo ra một Execution Context (Global hoặc Function), nó không chạy code ngay. Nó làm hai việc theo thứ tự:
1. Creation Phase (Chuẩn bị)
→ Tạo không gian cho biến và hàm
→ Thiết lập liên kết ra bên ngoài
→ Thiết lập `this`
2. Execution Phase (Thực thi)
→ Chạy từng dòng code
→ Gán giá trị cho biến
→ Thực thi expressionĐây là mental model pedagogical. Formal specification dùng thuật ngữ khác chi tiết hơn, nhưng predictive value là tương đương.
FUNCTION CALL
↓
┌──────────────────────────────┐
│ Creation Phase │
│ • Tạo chỗ cho biến/hàm │
│ • Thiết lập outer link │
│ • Thiết lập this │
└──────────────┬───────────────┘
↓
┌──────────────────────────────┐
│ Execution Phase │
│ • Chạy code từng dòng │
│ • Gán giá trị thực │
│ • Tính toán expression │
└──────────────┬───────────────┘
↓
returnĐây là simplification
Ở L2–L3, chúng ta hình dung Creation Phase là "chuẩn bị chỗ" và Execution Phase là "chạy code". Điều này đủ để dự đoán hoisting behavior. Chi tiết chính xác về Environment Record và Lexical Environment sẽ được dạy ở Module 1.2. this binding sẽ được dạy ở Stage 2.
Tư duy phòng khách sạn
Hãy tưởng tượng bạn thuê một phòng (tạo Execution Context):
- Creation Phase: Nhân viên dọn phòng, đặt sẵn tủ đựng đồ, treo sẵn móc áo — nhưng chưa có đồ của bạn. Họ chuẩn bị chỗ cho đồ.
- Execution Phase: Bạn vào phòng, đặt vali lên giường, treo áo lên móc — bạn đang dùng chỗ đã chuẩn bị.
Nếu bạn mở tủ trong lúc nhân viên đang dọn (giữa Creation và Execution), bạn thấy tủ trống hoặc chưa sẵn sàng — đó chính là lý do var tồn tại nhưng là undefined trước khi code gán giá trị.
5. Core Concepts (Các khái niệm cốt lõi)
Essential (Bắt buộc)
- Creation Phase: Giai đoạn engine chuẩn bị môi trường — tạo chỗ cho bindings, thiết lập outer reference, thiết lập
this - Execution Phase: Giai đoạn engine chạy code thực sự — gán giá trị, thực thi statement, tính expression
- Binding: Liên kết giữa tên biến/hàm và vị trí lưu trữ trong context
- Hoisting preview: Hàm declaration được "nhớ" trong Creation Phase, biến
varđược tạo nhưng chưa có giá trị
Supporting (Hỗ trợ)
vartrong Creation Phase: tạo binding, khởi tạoundefinedfunctiondeclaration trong Creation Phase: tạo binding, khởi tạo function objectlet/consttrong Creation Phase: tạo binding nhưng không khởi tạo (TDZ preview — Module 1.3)
Awareness (Biết tồn tại)
thisđược thiết lập trong Creation Phase, nhưng cơ chế chi tiết thuộc Stage 2- Lexical Environment và Environment Record là implementation detail của Creation Phase (Module 1.2)
Out of Scope (Không học trong bài này)
- Hoisting mechanism đầy đủ (Module 1.3)
- Temporal Dead Zone chi tiết (Module 1.3)
thisbinding rules (Stage 2)- Lexical Environment internals (Module 1.2)
- JIT compilation / hidden classes (Stage 11)
6. Worked Example (Ví dụ phân tích từng bước)
Xem đoạn code sau:
console.log(a);
console.log(b);
var a = 10;
function b() {
return 20;
}Bước 1 — Quan sát Có 4 dòng code. Nếu engine chạy từ trên xuống theo nghĩa đen, dòng 1 và 2 phải lỗi vì a và b chưa được định nghĩa.
Bước 2 — Phân loại
- Dòng 1–2: Execution Phase behavior (đọc biến)
- Dòng 3:
var a(declaration) += 10(initialization) - Dòng 4:
function b(declaration)
Bước 3 — Lý luận từng bước
1. Global Execution Context được tạo
2. CREATION PHASE bắt đầu
→ Engine quét toàn bộ code trong context
→ Thấy "var a" → tạo binding cho a, gán undefined
→ Thấy "function b" → tạo binding cho b, gán function object
→ Thấy console.log (không phải declaration, bỏ qua)
→ Thấy "= 10" là assignment → xử lý ở Execution Phase (không phải declaration, bỏ qua)
3. EXECUTION PHASE bắt đầu
→ Dòng 1: console.log(a)
→ a đã có binding từ Creation Phase
→ Giá trị hiện tại: undefined
→ Output: undefined
→ Dòng 2: console.log(b)
→ b đã có binding từ Creation Phase
→ Giá trị hiện tại: function object
→ Output: [Function: b]
→ Dòng 3: var a = 10
→ Declaration đã xử lý ở Creation Phase
→ Chỉ thực thi phần "= 10"
→ a = 10
→ Dòng 4: function b() {...}
→ Declaration đã xử lý ở Creation Phase
→ Không còn việc gì để làm ở dòng nàyBước 4 — Kết luậnvar và function được "chuẩn bị chỗ" trong Creation Phase, nên khi Execution Phase chạy đến, chúng đã tồn tại. var được khởi tạo undefined, còn function được khởi tạo sẵn function object.
7. Prediction Exercise (Bài tập dự đoán)
Đừng chạy code. Đọc và trả lời:
function test() {
console.log(x);
console.log(y);
var x = 5;
function y() {
return 10;
}
}
test();Câu hỏi:
console.log(x)in ra gì? Nó lấy giá trị từ đâu?console.log(y)in ra gì? Tại sao không phảiundefined?- Nếu đổi
var x = 5thànhlet x = 5,console.log(x)sẽ ra gì? (Hint:letkhông khởi tạo trong Creation Phase)
[Đáp án & Giải thích]
Bạn nghĩ
undefined— vìvar xđược tạo trong Creation Phase với giá trịundefined, nhưng= 5chưa chạy.[Function: y]— vìfunctiondeclaration được khởi tạo hoàn chỉnh trong Creation Phase.ReferenceError— vìlettạo binding trong Creation Phase nhưng không khởi tạo, để trong Temporal Dead Zone cho đến dòng khai báo.
Giải thích
- Khi
test()được gọi, tạo FEC chotest. - Creation Phase: engine quét body của
test, thấyvar x→ tạo binding vớiundefined; thấyfunction y→ tạo binding với function object. - Execution Phase: chạy từng dòng.
console.log(x)→xđã tồn tại, giá trịundefined.console.log(y)→yđã tồn tại, giá trị là function object.var x = 5→ gánx = 5.
- Nếu dùng
let x = 5: Creation Phase tạo binding choxnhưng không gán gì cả. Khiconsole.log(x)chạy, engine thấy binding tồn tại nhưng chưa được khởi tạo →ReferenceError: Cannot access 'x' before initialization. Đây là TDZ, sẽ học chi tiết ở Module 1.3.
- Khi
8. Implementation Lab (Bài lab thực hành)
Lab 1 — Trace Creation vs Execution (Guided)
Cho đoạn code sau. Hãy viết ra những gì xảy ra trong Creation Phase và Execution Phase của Function Execution Context setup():
function setup() {
console.log(status);
console.log(init);
var status = "ready";
function init() {
return "done";
}
}
setup();Gợi ý
- Creation Phase: engine chỉ quét declaration (
var,function), không chạyconsole.log - Execution Phase: engine chạy từng dòng từ trên xuống
[Đáp án tham khảo]
Creation Phase (trong FEC của setup)
- Quét body của
setup - Thấy
var status→ tạo bindingstatus = undefined - Thấy
function init→ tạo bindinginit = function object - Bỏ qua
console.logvà= "ready"(không phải declaration)
- Quét body của
Execution Phase
- Dòng 1:
console.log(status)→undefined - Dòng 2:
console.log(init)→[Function: init] - Dòng 3:
var status = "ready"→ gánstatus = "ready" - Dòng 4:
function init() {...}→ declaration đã xử lý, không làm gì thêm
- Dòng 1:
Lab 2 — Dự đoán Phase (Independent)
Cho đoạn code sau. Hãy xác định: dòng nào xảy ra trong Creation Phase, dòng nào xảy ra trong Execution Phase?
function app() {
const title = "JEM";
console.log(title);
helper();
function helper() {
console.log("help");
}
}
app();[Đáp án tham khảo]
Creation Phase của
app()- Quét body của
app - Thấy
const title→ tạo binding (không khởi tạo — TDZ) - Thấy
function helper→ tạo binding với function object - Bỏ qua
console.log,helper()call,= "JEM"
- Quét body của
Execution Phase của
app()const title = "JEM"→ khởi tạotitleconsole.log(title)→ in"JEM"helper()→ gọi hàm → tạo FEC mới chohelper
Creation Phase của
helper()- Không có declaration nào trong body của
helper - Không tạo binding nào
- Không có declaration nào trong body của
Execution Phase của
helper()console.log("help")→ in"help"
9. Edge Cases (Các trường hợp ngoại lệ)
Case 1 — Function expression không được "hoist" đầy đủ
console.log(a);
console.log(b);
var a = function () {
return 1;
};
function b() {
return 2;
}- What fails?
console.log(a)raundefined, không phải function - Why?
var a = function() {...}là function expression gán cho biếnvar. Trong Creation Phase, chỉvar ađược xử lý →a = undefined. Phần= function() {...}là assignment, chạy trong Execution Phase. Ngược lại,function b()là function declaration → được khởi tạo hoàn chỉnh trong Creation Phase. - How to observe?
console.log(a)→undefined,console.log(b)→[Function: b] - How to fix/decide? Nếu cần gọi hàm trước khi định nghĩa, dùng function declaration. Nếu cần conditional assignment, dùng function expression nhưng đừng gọi trước.
Case 2 — let/const tồn tại nhưng không dùng được trong Creation Phase
function demo() {
console.log(x);
let x = 10;
}
demo();- What fails?
ReferenceError: Cannot access 'x' before initialization - Why?
let xtạo binding trong Creation Phase, nhưng không khởi tạo. Binding nằm trong Temporal Dead Zone (TDZ) cho đến dòng khai báo. Khác vớivar(khởi tạoundefined),letkhông cho phép truy cập trước khi đến dòng khai báo. - How to observe? Chạy code và thấy
ReferenceErrorthay vìundefined - How to fix/decide? Khai báo biến trước khi dùng. Đây là lý do
let/constan toàn hơnvar— chúng ngăn bạn vô tình dùng biến chưa được khởi tạo.
10. Debug Lab (Bài lab gỡ lỗi)
Symptom (Triệu chứng): Developer báo cáo: "Tôi định nghĩa hàm calculate bằng var, nhưng khi gọi trước khai báo thì bị lỗi TypeError: calculate is not a function."
Reproduction (Tái hiện lỗi):
console.log(calculate(5));
var calculate = function (num) {
return num * 2;
};Evidence (Bằng chứng): TypeError: calculate is not a function thay vì ReferenceError.
Hypothesis (Giả thuyết): Developer nhầm lẫn giữa function declaration và function expression. var calculate = function() {...} là function expression gán cho biến var. Trong Creation Phase, chỉ var calculate được xử lý → calculate = undefined. Khi console.log(calculate(5)) chạy ở Execution Phase, calculate là undefined, không phải function → TypeError.
Verification (Xác minh): Đổi var calculate = function thành function calculate() — lỗi biến mất vì function declaration được khởi tạo hoàn chỉnh trong Creation Phase.
Root Cause (Nguyên nhân gốc rễ): Không phân biệt Creation Phase behavior giữa function declaration (khởi tạo sẵn function object) và function expression gán cho var (chỉ tạo binding undefined, assignment chạy sau ở Execution Phase).
Prevention (Phòng ngừa):
- Nếu cần gọi hàm trước định nghĩa, dùng
function calculate() {}(declaration) - Nếu dùng function expression, đảm bảo khai báo trước khi gọi
- Không dùng
varcho function expression nếu có thể dùngconst—constsẽ throwReferenceErrorrõ ràng hơnTypeErrormơ hồ
11. Design Exercise (Bài tập thiết kế giải pháp)
Không áp dụng ở Depth L2–L3.
12. Production Scenario (Tình huống thực tế)
Context: Một codebase legacy có nhiều file JavaScript được nối qua thẻ <script>. File thứ hai dùng một hàm được định nghĩa ở file thứ nhất.
Constraint: File 1 định nghĩa hàm bằng var process = function(data) {...}. File 2 gọi process(items) ở dòng đầu tiên.
Symptom: Khi tải trang, đôi khi thấy TypeError: process is not a function, đôi khi lại chạy bình thường.
Decision cần đưa ra: Dùng kiến thức về Creation Phase và Execution Phase, giải thích tại sao lỗi này xảy ra ngẫu nhiên (race condition giữa thứ tự load file và thứ tự chạy code), và đề xuất fix.
Gợi ý
Vấn đề không nằm ở Creation Phase/Execution Phase trong một file, mà ở thứ tự load script. Nếu File 2 load và chạy trước File 1, process chưa tồn tại. Tuy nhiên, nếu developer nghĩ var process = function sẽ "hoist" giống function process(), họ đã hiểu sai Creation Phase behavior. Fix: đổi thành function process(data) {...} (hoist hoàn toàn) hoặc đảm bảo thứ tự load + dùng event listener đợi DOM ready.
13. AI-Assisted Exercise (Bài tập với AI)
Level A — Ask
- Tự trả lời trước: Viết ra giấy: "Tại sao
function foo() {}có thể gọi trước khi định nghĩa, nhưngvar foo = function() {}thì không?" - Hỏi AI: Dùng prompt: "In JavaScript, why can I call a function before its declaration using 'function foo() {}', but not with 'var foo = function() {}'? Explain using execution context phases."
- So sánh: AI có nhắc đến Creation Phase và Execution Phase không? AI có phân biệt rõ function declaration vs function expression không? AI có dùng từ "hoisted" một cách mơ hồ cho cả hai trường hợp không?
- Verify: Mở MDN "Function", tìm phần "Function declaration hoisting" và "Function expression". Kiểm chứng xem AI có bỏ sót điểm nào.
Gợi ý
Để ý xem AI có nói "both are hoisted" không. Câu trả lời đúng cần phân biệt: function declaration được khởi tạo hoàn chỉnh trong Creation Phase; function expression gán cho var chỉ có biến được tạo (undefined), còn assignment chạy ở Execution Phase. Nếu AI gộp cả hai thành "hoisted", bạn đã tìm ra điểm mù.
Đáp án tham khảo
Bạn nghĩ
function foo() {}là function declaration. Trong Creation Phase, engine thấy declaration này và tạo binding hoàn chỉnh — gán sẵn function object. Nên khi Execution Phase chạy,foođã là function. Cònvar foo = function() {}là function expression gán cho biếnvar. Trong Creation Phase, chỉvar foođược xử lý →foo = undefined. Phần= function() {}là assignment, chạy trong Execution Phase. Nếu gọi trước assignment,foovẫn làundefined.AI trả lời
- "Both function declarations and var declarations are hoisted, but they behave differently."
- "A function declaration like
function foo() {}is hoisted with its full definition, so you can call it before the line where it appears." - "A function expression assigned to a var like
var foo = function() {}is hoisted only as a variable declaration. The assignment happens at runtime, so calling it before the assignment results inundefined." - "This is because of how JavaScript execution contexts work — declarations are processed in the creation phase, while assignments happen in the execution phase."
So sánh
- AI đúng về điểm chính: declaration hoàn chỉnh vs chỉ variable hoisted.
- AI có nhắc đến Creation Phase và Execution Phase — tốt.
- AI dùng từ "hoisted" cho cả hai trường hợp. Điều này kỹ thuật đúng nhưng dễ gây hiểu nhầm: learner có thể nghĩ "hoisted" nghĩa là giống nhau. Sự khác biệt nằm ở mức độ khởi tạo trong Creation Phase.
- AI không nhắc đến
let/constfunction expression — một điểm mù vìconst foo = function() {}sẽ throwReferenceErrorthay vìTypeError.
Điểm AI nói sai hoặc quá mơ hồ
- AI nói "both are hoisted" mà không làm rõ sự khác biệt về giá trị khởi tạo. Function declaration được gán function object ngay trong Creation Phase;
varchỉ được gánundefined. Đây là điểm then chốt để dự đoán behavior. - AI không nhắc đến
const foo = function() {}. Nếu dùngconstthay vìvar, việc gọi trước assignment sẽ throwReferenceError(do TDZ) thay vìTypeError— một điểm mù quan trọng khi chọn kiểu khai báo.
- AI nói "both are hoisted" mà không làm rõ sự khác biệt về giá trị khởi tạo. Function declaration được gán function object ngay trong Creation Phase;
Kết luận Nếu bạn phát hiện AI dùng "hoisted" như một từ chung chung mà không phân biệt mức độ khởi tạo, bạn đã hiểu sâu hơn AI về Creation Phase. Điều này sẽ cực kỳ quan trọng khi bạn học Module 1.3 (Hoisting & TDZ) và Module 1.4 (Closure), nơi sự khác biệt giữa "tạo binding" và "khởi tạo giá trị" quyết định behavior.
14. Teach Back (Dạy lại)
Yêu cầu: Giả sử một junior developer hỏi: "Tôi đọc trên mạng nói JavaScript 'hoist' biến và hàm. Tại sao console.log(foo) ra undefined nhưng console.log(bar) lại ra function khi cả hai đều được định nghĩa sau dòng console.log?"
console.log(foo);
console.log(bar);
var foo = 10;
function bar() {
return 20;
}Hãy giải thích trong 2 phút, dùng khái niệm Creation Phase và Execution Phase.
Mô phỏng
- Bạn nói Khi file này chạy, engine tạo Global Execution Context. Nhưng nó không chạy code ngay — nó có hai giai đoạn. Creation Phase là giai đoạn chuẩn bị: engine quét toàn bộ code, thấy
var foothì tạo chỗ chofoovà gánundefined; thấyfunction barthì tạo chỗ chobarvà gán luôn function object. Rồi đến Execution Phase: engine chạy từng dòng từ trên xuống. Dòng đầuconsole.log(foo)— lúc nàyfoođã có chỗ nhưng giá trị làundefinedvì phần= 10chưa chạy. Dòng haiconsole.log(bar)—barđã có sẵn function object từ Creation Phase nên in ra function. Vậy nên cả hai đều "hoist" về mặt declaration, nhưng mức độ chuẩn bị khác nhau:varchỉ chuẩn bị chỗ trống, cònfunctionchuẩn bị cả nội dung.
💡 Hình dung như setup một sự kiện: Creation Phase là lúc bạn đặt bàn ghế sẵn —
varlà đặt bàn trống,functionlà đặt bàn và xếp sẵn đồ ăn. Execution Phase là lúc khách đến. Nếu khách nhìn bànvartrước khi bạn dọn đồ lên, họ thấy trống (undefined). Nhưng bànfunctionđã có sẵn món ăn từ lúc setup.
Gợi ý đánh giá bản thân
- Đồng nghiệp có hiểu tại sao cả hai đều "tồn tại" nhưng giá trị khác nhau không?
- Bạn có dự đoán được câu hỏi tiếp: "Vậy
letthì sao?" không? (Trả lời:lettạo bàn nhưng dán băng keo "chưa được mở" — TDZ.) - Bạn có thể trace được nếu họ đổi
var foo = 10thànhfoo = 10(không khai báo) không? (Trả lời: Không có declaration → không tạo binding trong Creation Phase →ReferenceErrorở strict mode, hoặc tạo global property ở non-strict.)
15. Assessment (Đánh giá)
| Objective (Mục tiêu) | Hình thức đánh giá | Nội dung |
|---|---|---|
| Giải thích hai phase | Explain (Giải thích) | Liệt kê 3 thành phần chính của Creation Phase và 3 thành phần chính của Execution Phase |
| Creation vs Execution | Classification (Phân loại) | Cho đoạn code 10 dòng, phân loại dòng nào xảy ra ở Creation Phase, dòng nào ở Execution Phase |
| Dự đoán giá trị biến/hàm | Prediction (Dự đoán) | Cho 4 đoạn code có var/function/let, đoán output tại dòng trước khai báo |
| Trace luồng Creation → Execution | Trace (Truy vết) | Cho code có 1–2 hàm, viết thứ tự xảy ra trong mỗi phase |
16. Exit Criteria (Tiêu chí qua bài)
- [ ] Có thể giải thích tại sao Execution Context có hai phase (chuẩn bị trước, chạy sau)
- [ ] Có thể liệt kê ít nhất 2 việc xảy ra trong Creation Phase (tạo binding, thiết lập outer reference)
- [ ] Có thể dự đoán đúng giá trị của
vartrước dòng khai báo (undefined) trong 2/2 scenario - [ ] Có thể dự đoán đúng giá trị của
functiondeclaration trước dòng định nghĩa (function object) trong 2/2 scenario - [ ] Có thể phân biệt function declaration (khởi tạo hoàn chỉnh trong Creation Phase) và function expression gán cho
var(chỉ tạo bindingundefined) - [ ] Có thể trace timeline Creation → Execution cho một hàm có
varvàfunctiondeclaration
17. Spiral Connection (Liên kết xoắn ốc)
Previous (Trước): Lesson 1.1.1–1.1.3 — Bạn đã biết Execution Context là container, Global FEC luôn tồn tại, Function FEC được tạo mỗi khi gọi hàm và bị hủy khi return.
Current (Hiện tại): Bạn hiểu mỗi Execution Context có hai phase: Creation Phase (chuẩn bị bindings) và Execution Phase (chạy code). Bạn biết
varvàfunctiondeclaration được xử lý trong Creation Phase, nhưng với mức độ khởi tạo khác nhau.Next (Tiếp theo):
- 1.2.x — Scope & Lexical Environment (cơ chế engine tìm biến qua outer reference đã thiết lập trong Creation Phase)
- 1.3.x — Hoisting & Temporal Dead Zone (chi tiết hóa behavior của
var,let,const,classtrong Creation Phase)- 1.4.x — Closure (khi inner function giữ lại outer environment sau khi outer context đã kết thúc — ngoại lệ của "context bị hủy")
- S2 —
thisbinding (thiết lậpthistrong Creation Phase, chi tiết hóa ở Stage 2)- S11 — Memory & GC (context không bị hủy hoàn toàn nếu có reference giữ lại — nhưng đây là Stage 11, không học sớm)