← Foundations Course

FOUNDATIONS PHASE 2 · 19

JavaScript Deep:真正難的是 State、Reference、Time

JavaScript 初學最常見的錯,不是忘記某個 method,而是搞錯「這個值現在指向誰」「closure 還能看到什麼」「callback 什麼時候跑」。這一課集中練 execution trace。

Learning outcomes

1. Reference Sharing

const a = {
  score: 80
};

const b = a;

b.score = 95;

console.log(
  a.score
);
// 95

a/b 指向同一個 object,因此 mutation 對兩邊都可見。

2. Shallow Copy

const user = {
  profile: {
    city: "Tainan"
  }
};

const copy = {
  ...user
};

copy.profile.city =
  "Taipei";

外層是新 object,但 nested profile reference 仍共享。

3. Closure

function makeCounter() {
  let count = 0;

  return () => {
    count++;
    return count;
  };
}

const counter =
  makeCounter();

回傳 function 仍可存取建立時的 lexical binding。

4. Async Ordering

console.log("A");

Promise.resolve()
  .then(
    () => console.log("B")
  );

console.log("C");

// A
// C
// B

Callback 不是看到就同步執行。要分 current call stack 與之後排程工作。

5. Runtime Evidence

TypeError:
Cannot read properties of undefined
    at renderCourse (...)

Stack trace 告訴你 crash site;root cause 可能更早在 data shape、find() 回 undefined、async race。

Project checkpoint:Course Workspace State Trace

state:
courses = []
selectedId = null
status = "idle"

click Load
→ status = "loading"

response
→ courses = [...]
→ status = "success"

click card
→ selectedId = 42

把每個 event 對 state transition 寫清楚,UI bug 會容易定位很多。

Debug evidence:Stale State

如果 async request A 比後送的 B 晚回來,A 可能覆蓋較新的 state。這不是「網路亂掉」,而是程式缺少 cancellation/version guard。

Knowledge check

  1. object assignment 為什麼可能共享 mutation?
  2. spread 為什麼不是 deep copy?
  3. closure 保存的是值的快照嗎?
  4. 預測 A/C/B 並說明原因。