Lesson 1.3.4 — Temporal Dead Zone (TDZ — Vùng chết tạm thời)
0. Metadata (Thông tin bài học)
| Field | Value |
|---|---|
| Stage | 1 — JavaScript Execution Model |
| Module | 1.3 — Hoisting & Temporal Dead Zone |
| Lesson | 1.3.4 — Temporal Dead Zone |
| Competency | C01.2 — Variables & Bindings |
| Depth | L3–L4 (Use → Debug) |
| Prerequisites | Lesson 1.3.1 (Declaration vs Initialization), Lesson 1.3.2 (var), Lesson 1.3.3 (let/const) |
| Cognitive Load | High |
1. Why This Exists (Vì sao cần học)
Bạn đã học rằng let và const được declare trong Creation Phase nhưng không initialize cho đến dòng khai báo. Nhưng câu hỏi quan trọng hơn là:
Nếu binding đã tồn tại trong Environment Record, tại sao engine không cho phép truy cập nó? Tại sao không trả về
undefinednhưvar?
Câu trả lời nằm ở Temporal Dead Zone — một khái niệm mà nhiều developer biết tên nhưng không hiểu mechanism. Họ nghĩ TDZ là "khoảng thời gian trước dòng khai báo", nhưng không hiểu tại sao nó tồn tại và tại sao nó quan trọng.
Nếu không hiểu TDZ, bạn sẽ không bao giờ giải thích được tại sao đoạn code này throw error:
let x = x; // ReferenceError: Cannot access 'x' before initializationHoặc tại sao typeof — vốn an toàn với biến chưa tồn tại — lại fail trong TDZ:
typeof undeclaredVar; // "undefined"
typeof tdzVar; // ReferenceError!
let tdzVar = 1;Bài này xây dựng mental model chính xác về TDZ như trạng thái của binding, không phải khoảng thời gian.
2. Prerequisites (Yêu cầu đầu vào)
Trước khi học bài này, bạn cần:
- Phân biệt được Declaration, Initialization, Assignment (Lesson 1.3.1).
- Hiểu
varđược declare + initialize (undefined) trong Creation Phase (Lesson 1.3.2). - Hiểu
let/constđược declare trong Creation Phase nhưng không initialize (Lesson 1.3.3). - Biết
typeoftrả về"undefined"cho biến chưa tồn tại (Stage 0).
3. Learning Objectives (Mục tiêu học tập)
Sau bài này, bạn có thể:
- Giải thích Temporal Dead Zone là trạng thái của binding (uninitialized), không phải khoảng thời gian.
- Dự đoán khi nào code throw
ReferenceErrordo TDZ thay vì do biến không tồn tại. - Trace TDZ qua Creation Phase và Execution Phase cho
let,const, vàclass. - Debug bug TDZ trong code thực tế — đặc biệt khi refactor
var→lethoặc dùngtypeof.
4. Mental Model (Mô hình tư duy)
Mental Model: TDZ là Trạng thái Uninitialized
┌─────────────────────────────────────────┐
│ Lexical Scope (Block / Function) │
│ │
│ { │
│ ←── TDZ bắt đầu: binding 'x' │
│ được declare nhưng chưa │
│ initialize │
│ │
│ console.log(x); // ReferenceError │
│ │
│ let x = 10; ←── TDZ kết thúc: │
│ binding được initialize │
│ │
│ console.log(x); // 10 │
│ } │
└─────────────────────────────────────────┘TDZ không phải là "thời gian chờ". Nó là trạng thái của binding trong Environment Record:
- Trước TDZ: Binding chưa được declare → truy cập →
ReferenceError: x is not defined - Trong TDZ: Binding đã được declare nhưng chưa initialize → truy cập →
ReferenceError: Cannot access 'x' before initialization - Sau TDZ: Binding đã được initialize → truy cập → giá trị hợp lệ
Sai lầm phổ biến
"TDZ là khoảng thời gian từ đầu scope đến dòng khai báo."
Sai. TDZ không phải "thời gian" — nó là trạng thái uninitialized của binding. Điều quan trọng không phải "bao lâu" mà là binding đã tồn tại nhưng chưa sẵn sàng để dùng.
5. Core Concepts (Các khái niệm cốt lõi)
Essential (Bắt buộc)
| Concept | Định nghĩa |
|---|---|
| Temporal Dead Zone (TDZ) | Trạng thái của binding khi nó đã được declare trong Environment Record nhưng chưa được initialize. |
| TDZ Error Message | ReferenceError: Cannot access 'x' before initialization — khác với ReferenceError: x is not defined. |
| TDZ Start | Ngay đầu lexical scope chứa binding (sau dòng mở block {). |
| TDZ End | Tại dòng khai báo let/const/class, khi binding được initialize. |
| typeof trong TDZ | typeof throw ReferenceError nếu binding đang trong TDZ — khác với biến hoàn toàn không tồn tại. |
Supporting (Hỗ trợ)
- TDZ với
class:classdeclaration cũng có TDZ tương tựlet/const. - TDZ với default parameters: TDZ có thể xảy ra giữa các parameters của function.
Awareness (Biết tồn tại)
- TDZ với
consttrongfor-ofloop. - TDZ không áp dụng cho
varvìvarđược initialize ngay trong Creation Phase.
Out of Scope (Không học trong bài này)
- Chi tiết spec algorithm của
InitializeBindingvàGetBindingValue. - TDZ trong destructuring phức tạp (sẽ đề cập ở mức awareness nếu xuất hiện trong example).
6. Worked Example (Ví dụ phân tích từng bước)
Trace đoạn code sau:
function check() {
console.log(typeof value);
let value = 42;
console.log(value);
}
check();Step 1 — Creation Phase (Function Execution Context của check)
- Engine quét function body, thấy
let value. - Declaration: Tạo binding
valuetrong Block Environment Record củacheck. - Initialization: Không xảy ra. Binding ở trạng thái uninitialized → bắt đầu TDZ.
Trạng thái Environment Record:
value: <uninitialized> (TDZ active)Step 2 — Execution Phase
- Dòng 2:
console.log(typeof value)— engine cố gắng đọc binding đang trong TDZ. - Kết quả:
ReferenceError: Cannot access 'value' before initialization. - Lưu ý: Đây không phải
"undefined".typeofthường an toàn, nhưng không an toàn với TDZ.
Bây giờ so sánh với biến hoàn toàn không tồn tại:
console.log(typeof ghost); // "undefined"Step 1 — Resolution
- Engine tìm
ghosttrong tất cả Environment Records từ inner đến outer. - Không tìm thấy binding nào.
- Kết quả:
typeoftrả về"undefined"— đây là behavior đặc biệt củatypeof.
Code Review Lens
Khi debug ReferenceError, đọc kỹ message:
"x is not defined"→ binding không tồn tại trong bất kỳ scope nào."Cannot access 'x' before initialization"→ binding đã tồn tại nhưng đang trong TDZ.
7. Prediction Exercise (Bài tập dự đoán)
Prediction 1
Đừng chạy code. Dự đoán output hoặc error, và phân biệt loại lỗi.
{
console.log(a);
let a = 10;
}[Đáp án & Giải thích]
Bạn nghĩ
ReferenceError: Cannot access 'a' before initialization.- Binding
ađã được declare trong Creation Phase nhưng chưa initialize.
Giải thích
- TDZ bắt đầu từ đầu block
{. console.log(a)chạy trong TDZ → throw error.- Khác với
var— nếu dùngvar, output sẽ làundefined.
- TDZ bắt đầu từ đầu block
Prediction 2
Đừng chạy code. Dự đoán output hoặc error.
let x = x;[Đáp án & Giải thích]
Bạn nghĩ
ReferenceError: Cannot access 'x' before initialization.
Giải thích
- Dòng
let x = xthực hiện theo thứ tự:- Đánh giá right-hand side:
x→ binding đang trong TDZ → throw error. - Assignment chưa kịp xảy ra.
- Đánh giá right-hand side:
- Điều này chứng minh TDZ là trạng thái của binding, không phải "thời gian trước dòng khai báo". Ngay cả trong chính dòng khai báo, binding cũng chưa được initialize khi RHS được đánh giá.
- Dòng
Prediction 3 — Transfer Exercise
Đừng chạy code. Dự đoán output hoặc error.
function test(x = y, y = 1) {
console.log(x, y);
}
test();[Đáp án & Giải thích]
Bạn nghĩ
ReferenceError: Cannot access 'y' before initialization.
Giải thích
- Parameters của function có scope riêng.
yđược declare trong parameter scope nhưng chưa initialize khix = yđược đánh giá. yđang trong TDZ tại thời điểmxlấy giá trị default.- Đây là TDZ trong parameter list — ít gặp nhưng quan trọng.
- Parameters của function có scope riêng.
8. Implementation Lab (Bài lab thực hành)
Level 1 — Guided (Hướng dẫn)
Viết comment mô tả TDZ cho đoạn code sau:
function init() {
// TDZ của 'config' bắt đầu từ đây
console.log(config); // Error: Cannot access 'config' before initialization
let config = { env: "prod" }; // TDZ kết thúc
console.log(config); // { env: "prod" }
}Level 2 — Partial Scaffold (Khung mẫu một phần)
Điền loại lỗi hoặc output cho từng dòng:
console.log(typeof ghost); // ___ (binding không tồn tại)
let phantom = 1;
console.log(typeof phantom); // ___ (binding đã initialize)
{
console.log(typeof phantom); // ___ (truy cập từ inner scope)
console.log(typeof specter); // ___ (binding trong cùng block, chưa declare)
let specter = 2;
}Đáp án
console.log(typeof ghost); // "undefined" (binding không tồn tại)
let phantom = 1;
console.log(typeof phantom); // "number" (binding đã initialize)
{
console.log(typeof phantom); // "number" (truy cập từ inner scope, đã initialize)
console.log(typeof specter); // ReferenceError: Cannot access 'specter' before initialization
let specter = 2;
}Level 3 — Independent (Tự thực hiện)
Viết một function ngắn (tối đa 8 dòng) trong đó:
- Một biến
letđược log ra trước dòng khai báo và throw TDZ error. - Sử dụng
typeofvới biến đó (cũng throw TDZ error). - Sử dụng
typeofvới một biến hoàn toàn không tồn tại (trả về"undefined"). - Giải thích sự khác biệt giữa 3 trường hợp bằng đúng 2 khái niệm: TDZ, binding existence.
9. Edge Cases (Các trường hợp ngoại lệ)
Edge Case 1: TDZ với typeof
console.log(typeof ghost); // "undefined"console.log(typeof value); // ReferenceError!
let value = 1;typeof là toán tử duy nhất có thể truy cập biến không tồn tại mà không throw error. Nhưng nó không miễn nhiễm với TDZ. Điều này chứng minh TDZ binding đã tồn tại trong Environment Record — khác hoàn toàn với biến chưa được declare.
Edge Case 2: TDZ với class
const instance = new MyClass(); // ReferenceError!
class MyClass {
constructor() {
this.value = 42;
}
}class declaration cũng có TDZ tương tự let/const. Binding MyClass được declare trong Creation Phase nhưng chỉ được initialize (với class constructor) tại dòng khai báo.
Edge Case 3: TDZ trong Parameter Defaults
function test(a = b, b = 1) {
return a + b;
}
test(); // ReferenceError: Cannot access 'b' before initializationParameters được xử lý từ trái sang phải. Khi a = b được đánh giá, b đã được declare trong parameter scope nhưng chưa initialize → TDZ.
TIP
Trong production, tránh dependencies giữa parameters. Nếu a phụ thuộc b, hãy tính toán trong function body thay vì default parameter.
10. Debug Lab (Bài lab gỡ lỗi)
Symptom (Triệu chứng): Developer refactor var → let trong một module lớn. Một số test pass, một số throw ReferenceError.
function setupLogger() {
// Dòng 2: Sử dụng config trước khi khai báo
const level = config && config.level; // var: undefined (hoisted); let: ReferenceError (TDZ)
log("Logger initialized");
function log(message) {
console.log(`[${level || "info"}] ${message}`);
}
var config = getConfig(); // ← refactor từ var sang let ở đây
}Reproduction (Tái hiện lỗi): Khi đổi var config = getConfig() thành let config = getConfig(), dòng const level = config && config.level throw ReferenceError: Cannot access 'config' before initialization.
Evidence (Bằng chứng):
- Stack trace chỉ dòng
const config = getConfig(). - Code hoạt động bình thường với
var.
Hypothesis (Giả thuyết):
let configở cuối function được declare trong Creation Phase củasetupLogger, đưa binding vào TDZ từ đầu function body.- Dòng 2
const level = config && config.levelcố gắng đọc bindingconfigđang trong TDZ (uninitialized). - Với
var, binding được initialize thànhundefinedtrong Creation Phase, nênconfig && config.leveltrả vềundefinedvà code chạy — dù behavior có thể sai (dùng default level thay vì config thực).
Verification (Xác minh): Di chuyển let config = getConfig() lên trước dòng sử dụng:
function setupLogger() {
let config = getConfig(); // Khai báo + initialize trước khi dùng
const level = config && config.level;
log("Logger initialized");
function log(message) {
console.log(`[${level || "info"}] ${message}`);
}
}Code chạy. Giả thuyết đúng: lỗi là do đọc binding trong TDZ.
Root Cause (Nguyên nhân gốc rễ): Developer nghĩ var config; ở cuối function là "khai báo dự phòng" và refactor sang let config; với cùng intent. Họ không nhận ra let trong cùng scope sẽ đưa binding vào TDZ từ đầu function, ảnh hưởng đến tất cả code trước dòng khai báo.
Fix (Sửa): Xóa dòng var config; hoàn toàn vì config đã được khai báo bằng const ở đầu function.
Prevention (Phòng ngừa):
- Khi refactor
var→let/const, kiểm tra xem có khai báo trùng tên trong cùng scope không. - ESLint rule
no-redeclarevàno-use-before-definecó thể bắt lỗi này.
11. Design Exercise (Bài tập thiết kế giải pháp)
Depth L3–L4: Debug Decision (Quyết định gỡ lỗi)
Bạn nhận được bug report với stack trace sau:
// Bug report với stack trace sau:
// ReferenceError: Cannot access 'db' before initialization
// at connectDatabase (/app/db.js:12:18)
// Code:
function connectDatabase() {
const config = loadConfig();
// Dòng 12
const connection = createConnection(db.host, db.port);
// Dòng 15 — junior developer thêm ở cuối function vì thói quen "khai báo cuối" từ var
let db = config.database;
}Câu hỏi:
- Tại sao lỗi xảy ra ở dòng 12 khi
let dbở dòng 15? - Tại sao message là
"Cannot access 'db' before initialization"thay vì"db is not defined"? - Bạn sẽ fix như thế nào?
[Đáp án tham khảo]
Bạn nghĩ
- Dòng 15
let dbđược declare trong Creation Phase củaconnectDatabase, đưa binding vào TDZ từ đầu function body. - Dòng 12
createConnection(db.host, db.port)cố gắng đọc bindingdbđang trong TDZ (uninitialized) → throwReferenceError. - Message là
"Cannot access 'db' before initialization"vì binding đã tồn tại trong Environment Record nhưng chưa initialize. Khác với"db is not defined"— đó là khi binding không tồn tại trong bất kỳ scope nào.
- Dòng 15
Giải thích chính xác
let dbở cuối function vẫn được xử lý trong Creation Phase. Từ đầu function,dbđã tồn tại nhưng ở trạng thái uninitialized.- Dòng 12 chạy trong Execution Phase, trước khi dòng 15 initialize binding → TDZ error.
- Với
var db = config.database, binding được initialize thànhundefinedtrong Creation Phase, nên dòng 12 sẽ đọcundefined.host→TypeError(hoặc silent bug tùy implementation).
Fix
Di chuyển
let db = config.database;lên trước dòng 12:jsfunction connectDatabase() { const config = loadConfig(); let db = config.database; // Initialize trước khi dùng const connection = createConnection(db.host, db.port); }
Trade-off
- Junior developer thêm
let dbở cuối vì thói quen từvar(hoisted). Vớilet/const, declaration location quan trọng vì TDZ bắt đầu từ đầu scope, không phải từ dòng khai báo.
- Junior developer thêm
12. Production Scenario (Tình huống thực tế)
Bạn đang review PR refactor một file config từ var sang const:
// Trước
var API_URL = "https://api.example.com";
var TIMEOUT = 5000;
function init() {
console.log(API_URL);
var API_URL = "https://api.staging.com";
}
// Sau
const API_URL = "https://api.example.com";
const TIMEOUT = 5000;
function init() {
console.log(API_URL);
const API_URL = "https://api.staging.com";
}Câu hỏi:
- Code trước in ra gì? Tại sao?
- Code sau in ra gì? Tại sao?
- Developer nghĩ gì sai khi refactor?
[Đáp án tham khảo]
- Code trước: In
undefined. Vìvar API_URLtronginitđược hoisted (declare + initializeundefinedtrong Creation Phase), shadow biến global.console.logđọc localundefined. - Code sau: Throw
ReferenceError: Cannot access 'API_URL' before initialization. Vìconst API_URLtronginitđược declare trong Creation Phase nhưng chưa initialize.console.logchạy trong TDZ. - Sai lầm: Developer nghĩ
constchỉ là "var không đổi". Họ không nhận raconstcòn thay đổi initialization timing và tạo TDZ. Ngoài ra, dùng cùng tênAPI_URLcho cả global và local là bad practice dù vớivarhayconst.
13. AI-assisted Exercise (Bài tập với AI)
Level C — Delegate & Inspect (Giao phó & Kiểm tra)
Tự trả lời trước: Viết ra giấy định nghĩa TDZ của bạn. Bao gồm:
- TDZ là gì (trạng thái hay thời gian)?
- TDZ bắt đầu và kết thúc khi nào?
typeofbehavior với TDZ vs biến không tồn tại?
Hỏi AI: "Explain Temporal Dead Zone in JavaScript. Why does
typeofthrow an error for TDZ variables but return 'undefined' for undeclared variables?"So sánh: AI có nói TDZ là "time period" không? Nó có giải thích rõ sự khác biệt giữa 2 loại
ReferenceErrorkhông?Verify: Kiểm tra bằng MDN (từ khóa:
Temporal Dead Zone,let,typeof) hoặc ECMAScript spec.
Gợi ý
Để ý xem AI có nói "TDZ is the time before the variable is declared" không. Nếu có, đó là dấu hiệu mental model của AI đang dùng approximation thay vì engine mechanism. Bạn đã học rằng TDZ là trạng thái uninitialized của binding, không phải "khoảng thời gian".
Đáp án tham khảo
Bạn nghĩ
- TDZ là trạng thái uninitialized của binding trong Environment Record.
- Bắt đầu: từ đầu lexical scope chứa binding.
- Kết thúc: tại dòng khai báo
let/const/class. typeofvới undeclared:"undefined"(binding không tồn tại).typeofvới TDZ:ReferenceError(binding tồn tại nhưng uninitialized).
AI trả lời (mô phỏng phản hồi thực tế)
- "Temporal Dead Zone is the period between the start of a block and the variable declaration where you cannot access the variable."
- "During TDZ, accessing the variable throws a ReferenceError."
- "typeof returns 'undefined' for variables that don't exist, but throws for TDZ variables because the variable technically exists in the scope."
- "This happens because let and const are hoisted to the top of the block but not initialized."
So sánh
- AI đúng về behavior: TDZ throw error,
typeofkhác nhau giữa undeclared và TDZ. - AI thiếu depth: Nó vẫn dùng "period" / "time" để mô tả TDZ. Nó không nhấn mạnh rằng TDZ là trạng thái của binding trong Environment Record.
- AI nói "hoisted to the top of the block" — lại dùng "hoisted" như cơ chế.
- AI đúng về behavior: TDZ throw error,
Điểm AI nói sai hoặc quá mơ hồ
- AI nói "TDZ is the period between..." — câu này gây hiểu nhầm TDZ là thời gian. Thực tế, nếu engine pause giữa Creation Phase và Execution Phase trong 1 giây hay 1 năm, TDZ vẫn là cùng một trạng thái.
- AI nói "let and const are hoisted" — cách diễn đạt này dễ gây nhầm lẫn với
varhoisting.
Kết luận
- Nếu bạn chỉ ra được rằng TDZ là trạng thái uninitialized chứ không phải khoảng thời gian, và
typeofbehavior khác nhau vì một cái là "binding không tồn tại" còn một cái là "binding tồn tại nhưng chưa initialize", bạn đã hiểu sâu hơn AI. Concept này sẽ quay lại ở Stage 2 (Object mutation), Stage 3 (Async callbacks), và Stage 8 (React stale closure).
- Nếu bạn chỉ ra được rằng TDZ là trạng thái uninitialized chứ không phải khoảng thời gian, và
14. Teach Back (Dạy lại)
Yêu cầu: Giải thích cho một đồng nghiệp junior trong 2 phút:
"Tôi có hai đoạn code. Đoạn A throw
ReferenceError: x is not defined. Đoạn B throwReferenceError: Cannot access 'x' before initialization. Tại sao message khác nhau? Đoạn nào là TDZ? Dùng đúng terminology: binding, Environment Record, uninitialized. Không được dùng từ 'hoisted'."
// Đoạn A
console.log(ghost);
// Đoạn B
console.log(spirit);
let spirit = 1;Mô phỏng
- Bạn nói
- "Cả hai đều là
ReferenceError, nhưng nguyên nhân hoàn toàn khác nhau." - "Đoạn A:
ghostkhông tồn tại trong bất kỳ Environment Record nào. Engine tìm từ inner scope ra outer scope rồi global — không thấy binding nào tênghost. Kết quả:ReferenceError: ghost is not defined." - "Đoạn B:
spiritđã tồn tại trong Environment Record. Engine tìm thấy bindingspirittrong block scope. Nhưng binding này ở trạng thái uninitialized — nó đã được declare trong Creation Phase nhưng chưa được initialize." - "Khi engine cố đọc một binding uninitialized, nó throw
ReferenceError: Cannot access 'spirit' before initialization. Đây chính là Temporal Dead Zone." - "Điểm then chốt: TDZ không phải là 'thời gian chờ'. Nó là trạng thái của binding. Binding đã tồn tại nhưng chưa sẵn sàng để dùng."
- "Nếu đồng nghiệp hỏi 'vậy làm sao sửa?', câu trả lời đơn giản: đừng đọc biến trước dòng khai báo."
- "Cả hai đều là
💡 Liên tưởng (Analogy — dùng ở L2–L3): Tưởng tượng một căn phòng. Đoạn A là bạn gõ cửa phòng không tồn tại — không ai trả lời. Đoạn B là bạn gõ cửa phòng có người, nhưng người đó chưa mặc quần áo xong — họ hét "Đợi đã!" (
ReferenceError). Cả hai đều không cho bạn vào, nhưng lý do hoàn toàn khác nhau.Lưu ý: Đây là analogy để phân biệt "binding không tồn tại" vs "binding uninitialized". Ở level cao hơn (S11+), bạn cần reasoning trực tiếp qua Environment Record và spec algorithm thay vì analogy.
Gợi ý đánh giá bản thân
- Đồng nghiệp có hiểu tại sao
typeof ghosttrả về"undefined"nhưngtypeof spiritthrow error không? - Bạn có thể dự đoán được behavior nếu thêm
var spirit;ở đầu scope không? - Nếu đồng nghiệp hỏi "TDZ kéo dài bao lâu?", bạn trả lời được không mà không dùng từ "thời gian"?
15. Assessment (Đánh giá)
| Objective (Mục tiêu) | Hình thức đánh giá | Depth |
|---|---|---|
| Giải thích TDZ là trạng thái uninitialized | Explain (Giải thích) + Teach Back | L2–L3 |
| Phân biệt TDZ error vs undeclared error | Prediction (Dự đoán) + Debug | L3–L4 |
Dự đoán typeof behavior với TDZ | Prediction (Dự đoán) | L3 |
Debug bug TDZ khi refactor var → let | Debug Lab (Gỡ lỗi) | L4 |
| Trace TDZ qua Creation/Execution Phase | Worked Example + Prediction | L3–L4 |
16. Exit Criteria (Tiêu chí qua bài)
- [ ] Có thể giải thích Temporal Dead Zone là trạng thái uninitialized của binding, không phải khoảng thời gian.
- [ ] Có thể phân biệt
ReferenceError: x is not defined(binding không tồn tại) vàReferenceError: Cannot access 'x' before initialization(binding trong TDZ). - [ ] Có thể dự đoán
typeofbehavior:"undefined"cho undeclared,ReferenceErrorcho TDZ. - [ ] Có thể trace TDZ qua Creation Phase và Execution Phase cho
let,const, vàclass. - [ ] Có thể debug bug TDZ trong code refactor từ
varsanglet/const. - [ ] Có thể dự đoán đúng 3/3 scenarios trong Prediction Exercise mà không chạy code.
17. Spiral Connection (Liên kết xoắn ốc)
Previous (Trước):
let/const→ bạn đã biết cả hai đều là block-scoped bindings được declare trong Creation Phase nhưng không initialize cho đến dòng khai báo.
Current (Hiện tại): Temporal Dead Zone → bạn hiểu rằng TDZ là trạng thái uninitialized của binding trong Environment Record, và sự khác biệt giữa "binding không tồn tại" và "binding tồn tại nhưng chưa initialize".
Next (Tiếp theo):
- 1.3.5 (Hoisting không phải một cơ chế duy nhất): Tổng hợp behavior của
var,let,const,function,class— mỗi loại có declaration và initialization timing khác nhau.- 1.3.6 (Hoisting trong Function): So sánh
varvàlettrong cùng một function bằng environment model.- 1.4 (Closure): Closure giữ reference đến Environment Record. Để hiểu stale closure và memory retention, bạn cần biết binding trong environment đã ở trạng thái nào — initialize hay uninitialized.