← Systems Foundations

COMPUTER SCIENCE · 77

Memory / Stack / Heap / Reference:Variable Name 不是 Object 本身

初學者常把「變數」、「值」、「物件」混成同一件事。真正 debug mutation、closure、pointer/reference、GC 時,需要至少有一個簡化但正確的 runtime memory model。

Learning outcomes

1. Primitive assignment

let a = 10;
let b = a;

b = 20;

console.log(a);
// 10

在這個抽象層可以把 number 視為 value copy;改 b 不會回頭改 a。

2. Object reference

const a = {
  score: 80
};

const b = a;

b.score = 95;

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

a/b 都能指向同一個 object,這叫 aliasing。修改 object state,所有持有該 reference 的地方都可能觀察到。

3. Call stack 保存 active calls

main()
  ↓ calls
loadCourses()
  ↓ calls
parseCourse()

每個 active function call 有自己的 execution context/frame;return 後 frame 退出 stack。

4. Heap 是長壽命 dynamic objects 的簡化模型

不同 runtime 實作細節不同,但概念上 object/closure 等資料常不只跟單一 call frame 同生共死。JavaScript 有 garbage collector;C++ 則可能要靠 value lifetime / RAII / smart pointer 管 ownership。

stack:
  a ─────┐
  b ─────┤
         ▼
heap-like object:
  { score: 95 }

5. Memory leak 的語意

GC 語言也會 leak:只要不再需要的 object 仍被 reachable reference 保留,collector 就不能回收。例如 global cache、event listener、closure 長期抓住大物件。

Project checkpoint:Shared Course State

故意讓兩個 modules 共用同一 object reference,再做 shallow copy,比較 mutation 會傳到哪裡。

const original = {
  meta: {
    title: "JS"
  }
};

const copy = {
  ...original
};

copy.meta.title =
  "TypeScript";

Spread 只 shallow copy;nested meta reference 仍共享。

Debug evidence:資料「莫名其妙」被改

先找誰持有同一 object reference、哪裡做 in-place mutation。不要因為畫面錯就只查 rendering code。

Knowledge check

  1. Primitive copy 與 object reference copy 差在哪?
  2. Call stack 保存什麼?
  3. GC 語言為何仍會 memory leak?
  4. 解釋 shallow copy 為什麼不會深度複製 nested object。