COMPUTER SCIENCE · 77
Memory / Stack / Heap / Reference:Variable Name 不是 Object 本身
初學者常把「變數」、「值」、「物件」混成同一件事。真正 debug mutation、closure、pointer/reference、GC 時,需要至少有一個簡化但正確的 runtime memory model。
Learning outcomes
- 能區分 primitive value 與 object reference 的基本模型。
- 能解釋 function call frame / call stack。
- 能理解 heap allocation 是 runtime memory 管理概念。
- 能說明 aliasing 為什麼導致 shared mutation。
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);
// 95a/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
- Primitive copy 與 object reference copy 差在哪?
- Call stack 保存什麼?
- GC 語言為何仍會 memory leak?
- 解釋 shallow copy 為什麼不會深度複製 nested object。