Lesson 0.1.1 — JavaScript là gì?
0. Metadata
| Thuộc tính | Giá trị |
|---|---|
| Stage | 0 |
| Module | 0.1 — JavaScript & Runtime Fundamentals |
| Lesson | 0.1.1 |
| Competency | C01 — JavaScript Language |
| Depth | L2–L3 (Explain → Use) |
| Prerequisites | Không |
| Cognitive Load | Thấp–Trung bình |
1. Why This Exists
Bạn viết một đoạn JavaScript đơn giản:
console.log(typeof document);Chạy trong Browser, kết quả là "object".
Chạy trong Node.js, kết quả là "undefined".
Cùng một ngôn ngữ. Cùng một câu lệnh. Kết quả khác nhau.
WARNING
Nếu bạn nghĩ "JavaScript là một ngôn ngữ và nó chạy như nhau ở mọi nơi", bạn đang thiếu một mental model quan trọng. Đây là nguyên nhân gốc rễ của hàng loạt bug production — đặc biệt là khi code được share giữa client và server (SSR).
Bài học này tồn tại để bạn hiểu:
JavaScript không chạy trong chân không. Nó chạy trong một hệ sinh thái gồm nhiều lớp. Việc không phân biệt các lớp đó là lý do bạn không thể giải thích tại sao
documentbiến mất.
2. Prerequisites
Không có. Đây là lesson đầu tiên của curriculum.
3. Learning Objectives
Sau bài học này, bạn có thể:
- Phân biệt ECMAScript, JavaScript Engine, và Host Environment.
- Phân loại một API là language feature hay host API.
- Giải thích tại sao cùng một đoạn code cho kết quả khác nhau ở Browser và Node.js.
- Dự đoán behavior đơn giản dựa trên runtime environment.
4. Mental Model
Hãy hình dung JavaScript hoạt động qua 4 lớp:
┌─────────────────────────────────────┐ │ 4. Host APIs │ │ (document, fs, fetch, process) │ ├─────────────────────────────────────┤ │ 3. Host Environment │ │ (Browser, Node.js, Deno, Bun) │ ├─────────────────────────────────────┤ │ 2. JavaScript Engine │ │ (V8, SpiderMonkey, JavaScriptCore) │ ├─────────────────────────────────────┤ │ 1. ECMAScript Specification │ │ (Language rules) │ └─────────────────────────────────────┘
Mental Model
- ECMAScript là bộ quy tắc (specification). Nó mô tả cú pháp, kiểu dữ liệu, toán tử, cách hàm hoạt động... Nó không phải code chạy được.
- JavaScript Engine là chương trình thực tế (V8 trong Chrome/Node.js, SpiderMonkey trong Firefox, JavaScriptCore trong Safari). Nó đọc code của bạn và thực thi theo đúng quy tắc của ECMAScript.
- Host Environment là nền tảng cung cấp "sân chơi" cho engine: Browser cung cấp DOM, Node.js cung cấp
fsvàprocess. - Host APIs là các công cụ mà Host Environment đưa vào runtime để bạn sử dụng.
Quan trọng: Engine chỉ đảm bảo Array.prototype.map hoạt động đúng. Engine không đảm bảo document tồn tại. document là quà tặng từ Browser.
5. Core Concepts
Essential — Bắt buộc nắm vững
| Khái niệm | Định nghĩa |
|---|---|
| ECMAScript | Bộ specification chuẩn hóa phần core language của JavaScript. Được duy trì bởi TC39. |
| JavaScript Engine | Chương trình thực thi JavaScript source code theo ECMAScript spec. |
| Host Environment | Nền tảng (Browser, Node.js, v.v.) cung cấp runtime context và APIs bên ngoài language core. |
| Runtime | Tổng thể: Engine + Host Environment + các APIs sẵn có tại thời điểm chạy. |
Supporting — Cần biết để hiểu context
- Các engine phổ biến: V8 (Chrome, Edge, Node.js), SpiderMonkey (Firefox), JavaScriptCore (Safari).
- Các host phổ biến: Browser, Node.js, Deno, Bun.
Awareness — Biết tồn tại, chưa cần master
- TC39, ECMA-262, và chu kỳ release hàng năm (ES2015, ES2023, v.v.).
- Engine có thể implement spec với các tối ưu khác nhau.
Out of Scope — Không học trong bài này
Out of Scope
- JIT compilation, hidden classes, inline caching → Stage 11
- Garbage Collector internals → Stage 11
- Execution Context, Lexical Environment → Stage 1
- Module system (ESM/CJS) → Stage 7
6. Worked Example
Hãy cùng phân tích từng bước: document là gì?
console.log(typeof document);Bước 1 — Nhận diện token: document là một identifier (tên biến/tên API).
Bước 2 — Tra cứu: Engine tìm document trong global scope.
Bước 3 — Kiểm tra nguồn gốc: document không nằm trong ECMAScript spec. Nó không được định nghĩa là một built-in của language core.
Bước 4 — Kiểm tra Host: Browser cung cấp document như một global object đại diện cho DOM tree. Node.js không cung cấp DOM, nên không có document.
Bước 5 — Kết luận:
- Browser →
typeof document === "object" - Node.js →
typeof document === "undefined"
Code Review Lens
Khi review code, hãy tự hỏi: "API này thuộc lớp nào?" Nếu bạn thấy document hoặc window trong một file utility "tưởng chừng pure", đó là red flag cho SSR hoặc unit test.
7. Prediction Exercise
Đừng chạy code. Đọc và dự đoán kết quả, sau đó giải thích tại sao.
Câu 1 — Trong Browser:
console.log(typeof Array);
console.log(typeof fetch);
console.log(typeof process);Câu 2 — Trong Node.js:
console.log(typeof Array);
console.log(typeof fetch);
console.log(typeof process);Câu 3 — Trong cả hai:
console.log(typeof (() => {}));Sau khi dự đoán xong, mở DevTools (Browser) và terminal (Node.js) để verify. Nếu sai, quay lại Mental Model ở Section 4.
8. Implementation Lab
Mục tiêu: Viết một hàm đơn giản để detect environment.
function detectEnvironment() {
if (typeof document !== "undefined") {
return "browser";
}
if (typeof process !== "undefined") {
return "node";
}
return "unknown";
}
console.log(detectEnvironment());TIP
typeof someVariable an toàn ngay cả khi someVariable chưa được khai báo. Đây là lý do ta dùng typeof thay vì if (document) — vì document không tồn tại sẽ throw ReferenceError.
9. Edge Cases
Edge Case 1: fetch đã "di cư"
fetch từng là API chỉ có trong Browser. Từ Node.js 18+, fetch được cung cấp như một global Web API.
WARNING
Điều này không có nghĩa fetch là language feature. Nó vẫn là Host API — chỉ là Node.js quyết định "mượn" API đó từ Web platform. Nếu bạn nhầm fetch là ECMAScript built-in, bạn sẽ bối rối khi gặp environment không hỗ trợ nó.
Edge Case 2: globalThis
console.log(globalThis);- Browser → trỏ đến
window - Node.js → trỏ đến
global - Web Worker → trỏ đến
self
globalThis là language feature (ECMAScript 2020) giúp truy cập global object một cách nhất quán cross-environment.
10. Debug Lab
Symptom: Bạn chạy một script bằng Node.js và nhận lỗi:
ReferenceError: document is not definedReproduction:
// utils.js
export function getTitle() {
return document.title;
}// test.js (chạy bằng Node.js)
import { getTitle } from "./utils.js";
console.log(getTitle());Evidence: Stack trace chỉ ra dòng return document.title;.
Hypothesis: document là Browser API. Node.js runtime không cung cấp DOM.
Verification: Chạy console.log(typeof document) trong Node.js → "undefined".
Root Cause: Confusion giữa language layer và host layer. Code giả định DOM tồn tại nhưng đang chạy trong host không có DOM.
Fix: Tách logic phụ thuộc DOM ra một module riêng, hoặc guard:
export function getTitle() {
if (typeof document === "undefined") {
return null; // hoặc throw domain-specific error
}
return document.title;
}Prevention: Luôn hỏi "API này thuộc host nào?" trước khi viết code dùng chung giữa client và server.
11. Design Exercise
Không áp dụng ở depth L2–L3. Design exercise sẽ xuất hiện từ các lesson L5+.
12. Production Scenario
Context: Bạn đang làm một ứng dụng Next.js (SSR). Component Header cần đọc window.location.pathname để highlight tab đang active.
Symptom: Server render bị crash với window is not defined.
Câu hỏi:
- Tại sao
windowkhông tồn tại khi server render? - Bạn nên guard như thế nào?
- Đây là lỗi ở lớp nào của mental model?
Gợi ý
window là Browser Host API. Server (Node.js) không có window. Bạn phải đảm bảo code truy cập window chỉ chạy ở client-side, hoặc dùng typeof window !== "undefined".
Đây là lỗi lớp 3–4 (Host Environment), không phải lỗi lớp 1–2 (ECMAScript/Engine).
13. AI-Assisted Exercise
Level A — Ask
- Tự viết một đoạn giải thích: "ECMAScript và JavaScript khác nhau thế nào?"
- Hỏi AI cùng câu hỏi đó.
- So sánh câu trả lời của bạn với AI.
- Tìm ít nhất một điểm AI nói sai hoặc quá mơ hồ.
TIP
AI thường nói "ECMAScript là tiêu chuẩn, JavaScript là implementation". Hãy kiểm tra xem AI có nhấn mạnh vai trò của Host Environment và Host APIs không. Nếu không, bạn hiểu sâu hơn AI ở khía cạnh này.
14. Teach Back
Trong 2 phút, giải thích cho một đồng nghiệp:
"Tại sao cùng một file JavaScript, chạy trong Browser thì
typeof document === "object", nhưng chạy trong Node.js thìtypeof document === "undefined"?"
Yêu cầu:
- Dùng đúng terminology: ECMAScript, Engine, Host, Runtime.
- Không được nói "Node.js không hỗ trợ document" mà không giải thích tại sao.
- Vẽ (hoặc mô tả) 4 lớp mental model.
15. Assessment
| Objective | Hình thức đánh giá |
|---|---|
| Phân biệt ECMAScript / Engine / Host | Classification — 8/10 API phân loại đúng |
| Dự đoán environment-specific behavior | Prediction — 3/3 scenarios đúng |
Giải thích lỗi document is not defined | Explain — dùng mental model 4 lớp |
| Detect runtime an toàn | Implementation — typeof guard đúng |
16. Exit Criteria
Bạn PASS lesson này khi:
- [ ] Có thể phân biệt ECMAScript, JavaScript Engine, và Host Environment.
- [ ] Có thể phân loại một API bất kỳ thành language feature hoặc host API.
- [ ] Có thể dự đoán đúng behavior của
typeofvới global APIs ở 2 environment khác nhau. - [ ] Có thể giải thích lỗi
document is not definedbằng mental model 4 lớp (không trả lời bằng intuition). - [ ] Có thể viết guard check an toàn bằng
typeofđể tránhReferenceError.
17. Spiral Connection
Previous → Không có. Đây là lesson đầu tiên của toàn bộ curriculum.
Current → Mental model 4 lớp: ECMAScript → Engine → Host → APIs
Next
→ Lesson 0.1.2: Browser vs Node.js (đi sâu vào từng host)
→ Stage 1: Execution Model (đi sâu vào Engine layer)
→ Stage 4: Browser Runtime (đi sâu vào Host APIs)
→ Stage 11: Performance & Engine Internals (JIT, GC, Hidden Classes)
INFO
Mental model bạn học hôm nay sẽ được tái sử dụng liên tục. Khi học Closure (Stage 1), bạn sẽ hiểu Engine quản lý scope như thế nào. Khi học React SSR (Stage 10), bạn sẽ quay lại câu hỏi: "API này thuộc host nào?" Đây chính là spiral learning.