Skip to content

Lesson 0.1.1 — JavaScript là gì?

0. Metadata

Thuộc tínhGiá trị
Stage0
Module0.1 — JavaScript & Runtime Fundamentals
Lesson0.1.1
CompetencyC01 — JavaScript Language
DepthL2–L3 (Explain → Use)
PrerequisitesKhông
Cognitive LoadThấp–Trung bình

1. Why This Exists

Bạn viết một đoạn JavaScript đơn giản:

js
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 document biế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ể:

  1. Phân biệt ECMAScript, JavaScript Engine, và Host Environment.
  2. Phân loại một API là language feature hay host API.
  3. 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.
  4. 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

  • ECMAScriptbộ 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 fsprocess.
  • 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
ECMAScriptBộ specification chuẩn hóa phần core language của JavaScript. Được duy trì bởi TC39.
JavaScript EngineChương trình thực thi JavaScript source code theo ECMAScript spec.
Host EnvironmentNền tảng (Browser, Node.js, v.v.) cung cấp runtime context và APIs bên ngoài language core.
RuntimeTổ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ì?

js
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:

js
console.log(typeof Array);
console.log(typeof fetch);
console.log(typeof process);

Câu 2 — Trong Node.js:

js
console.log(typeof Array);
console.log(typeof fetch);
console.log(typeof process);

Câu 3 — Trong cả hai:

js
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.

js
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

js
console.log(globalThis);
  • Browser → trỏ đến window
  • Node.js → trỏ đến global
  • Web Worker → trỏ đến self

globalThislanguage 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 defined

Reproduction:

js
// utils.js
export function getTitle() {
  return document.title;
}
js
// 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:

js
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:

  1. Tại sao window không tồn tại khi server render?
  2. Bạn nên guard như thế nào?
  3. Đâ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

  1. Tự viết một đoạn giải thích: "ECMAScript và JavaScript khác nhau thế nào?"
  2. Hỏi AI cùng câu hỏi đó.
  3. So sánh câu trả lời của bạn với AI.
  4. 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 EnvironmentHost 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

ObjectiveHình thức đánh giá
Phân biệt ECMAScript / Engine / HostClassification — 8/10 API phân loại đúng
Dự đoán environment-specific behaviorPrediction — 3/3 scenarios đúng
Giải thích lỗi document is not definedExplain — dùng mental model 4 lớp
Detect runtime an toànImplementation — 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 typeof với global APIs ở 2 environment khác nhau.
  • [ ] Có thể giải thích lỗi document is not defined bằ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ánh ReferenceError.

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.