跳至主要内容

本章為 JavaScript 核心重構的第五天,將帶領你揭開記憶體底層的傳值 (Pass by Value) 與傳址 (Pass by Reference) 之謎。透過「影印術」與「倉庫提貨單」的比喻,解析複雜物件分身術所造成的意外連動災難(改了 A 卻壞了 B),並初步介紹如何運用解構語法 (Destructuring) 建立安全的資料副本,穩固高階開發中至關重要的不可變性 (Immutability) 觀念基礎。

Day 05: 原理篇 —— 改了 A 卻壞了 B?記憶體傳址與副本的真相

本文同步分享於2026鐵人賽:JS 核心重構:勇者轉職傳說


📜 這裡的修煉規則

孩子,在踏上今日的領地前,先坐下來喝杯酒吧。 修煉的路很長,別急著奔跑,先聽聽這份卷軸裡的古老叮嚀。

我在每一站的盡頭都為你鋪設了 實戰演武場 CodePen。那不只是程式碼的拼湊,而是你在這場暴風雨中,試圖用邏輯點燃的一顆星火。 成功突圍後,別忘了帶著你的戰利品回到 QuestBoard 佈告欄。在那裡,你會發現自己從不孤單,公會的夥伴們都正舉杯等待你的歸來。

記住...

導師看重的從來不是你的劍法有多華麗,而是當你被邏輯擊潰、滿身泥濘後,依然選擇握緊理性的劍柄,再次向真相發起衝鋒的勇氣。


🛡️ 【公會大廳:導師的修煉導讀】

「導師!公會的裝備庫鬧鬼了!」一個新手冒險者滿頭大汗地跑過來。

「我明明是幫辛梅爾把公會的『藍色鎧甲』複製了一套給他用,結果辛梅爾為了帥氣把他的鎧甲漆成紅色,結果... 裝備庫裡所有待命的鎧甲居然都變成紅色的了!」他指著原本清一色藍色的儲物箱。

我笑了笑,接過他的卷軸一看,發現他寫著 let ximmelArmor = guildArmor;

孩子,這就是 JavaScript 世界裡最著名的 「靈異分身案」。在記憶體的底層,並非所有東西都是「影印」一份給你。有些時候,他給你的只是一張 「404 號儲物櫃的提貨單」。如果你不懂這個真相,你的資料庫將會出現各種莫名的連動反應。今天,我們要來拆穿這個「提貨單」的詭計。


💡 【導師講義:底層真相探究】

1. 傳值 (Pass by Value):影印術

對於簡單的物資(如數字、字串、布林值),JavaScript 很大方,每次賦值都是直接 「影印一份新副本」 給你。兩者從此各走各路,互不相干。

index.js
let myGold = 100;
let ximmelGold = myGold; // 💰 純粹的數值影印

ximmelGold = 500;
// 導師診斷:myGold 依然是 100,因為它們是兩張獨立的影印件。

2. 傳址 (Pass by Reference):提貨單

對於複雜的裝備箱(物件、陣列),JavaScript 其實很懶。它不會幫你搬運整個大箱子,而是給你一張標註了 「記憶體位置 (Address)」 的提貨單。

如果你把提貨單給了別人,當那個人按照單子去倉庫修改了內容,你手中的提貨單指向的內容也就跟著變了。

index.js
// 📦 這是一個公會共用鎧甲物件
const guildArmor = { color: "Blue" };

// ⚠️ 注意!這裡不是複製鎧甲,而是複製「提貨單」!
const ximmelArmor = guildArmor;

ximmelArmor.color = "Red";

console.log(guildArmor.color);
// 輸出:Red (導師驚嘆:連公會的鎧甲都跟著變紅了!)
🏹 導師的辨析圖:傳值 vs 傳址
特性傳值 (Value)傳址 (Reference)
類型基礎型別 (Number, String...)物件型別 (Object, Array...)
記憶體行為建立獨立的新空間共用同一個空間位址
修動 A 的後果B 不受任何影響B 同步發生變化

3. 邏輯流向圖解

導師的圖解心法: 傳值(Value)就像是把金幣拿出來,「再造一個完全一模一樣的影本」 放進新櫃子。而傳址(Reference)則是把 「第 404 號櫃子的提貨單」 複製一份交給你。你們兩個手上拿著不同的單子,但領的是同一個櫃子裡的貨!

傳值傳址真相圖


⚔️ 【戰術對抗:學長與學弟的代碼對決】

招式示範:物件的「分身術」與陷阱

❌ 冒險學弟:誤信為真的分身

  • 負能量評級:🔴 導致連鎖錯誤 / 🔴 邏輯難以追查
index.js
const teamBase = { hp: 100 };
const shadowA = teamBase; // 只是拿到了同張門票

shadowA.hp = 0; // ⚠️ 慘劇發生:全隊 HP 都歸零了

✅ 勇者學長:斷開靈魂的備份

  • 利潤評級:🟢 資料互不干涉 / 🟢 操作安全性極高
index.js
const teamBase = { hp: 100 };

// 🛠️ 真正的副本法 (今天先學最快的一招:解構與展開)
const safeBackup = { ...teamBase };

safeBackup.hp = 0; // 🛡️ 放心修改,原版 teamBase 依然健康
💡 導師講評

學長的寫法利用了 「解構 (Destructuring)」 的力量。他不是拿走原本的提貨單,而是按照清單內容,重新去另一個倉庫打造了一套一模一樣、但完全獨立的裝備。


🏰 【勇者精英課:邁向職人的進階架構】

1. 什麼是 const 鎖不住的真相?

孩子,你可能會問:為什麼我用了 const 宣告物件,我還是能修改裡面的顏色? 那是因為 const 鎖住的是那張 「提貨單 (位址)」 換不得,但他並不阻止你拿著這張單子去倉庫裡更換裝修。如果你想讓鎧甲連漆都不能漆(極致防禦),你需要施展 Object.freeze(obj)

2. 未來的不可變性 (Immutability)

在未來的高階架構中,為了讓系統穩定、不互打,我們幾乎不改動原始資料(Do not mutate input)。我們永遠採取「領取資料 -> 複製一份 -> 修改複本 -> 回報成果」。理解了「傳址」,你才拿到了這門技術的敲門磚。


🛖 【營火叮嚀:為什麼「淺拷貝」有時會失靈?】

⚠️ 實戰雷區:避開那些致命陷阱

孩子,今天學的 { ...obj } 是這套公會神技中的「影印機」。

但要注意,這台影印機是 「淺層掃瞄 (Shallow Copy)」。如果你在鎧甲箱子裡又裝了一個「零件箱」,它依然會發生靈魂連結。

記住導師的一句話: 「任何點(.)出來的第二層物件,依然帶著提貨單的詛咒。」如何徹底斷開所有層級的連結,那就是我們在未來「鍊金術」中要修煉的課題。


天色微亮,營火雖已燃盡,但你眼中卻閃爍著領悟的光芒。在前往演武場挑戰關卡前,我已經幫你把靈魂碎片精煉成了這份「戰術錦囊」。拿好它,今日的任務不再是負擔。

📝 【夥伴筆記:今日修煉精華】

這份筆記是你的隨身護身符,卡關時看一眼,真相就在裡面。

  • 基礎傳值:影印術,兩者無關。
  • 物件傳址:拿提貨單,改 A 壞 B。
  • 不可變性:不修改原始物件,透過備份複本來操作。

🎯 【實戰演武場】

  1. 📜 本日實戰任務:【原理】改了 A 卻壞了 B?記憶體傳址與副本的真相 (CodePen)
  2. 將 CodePen 網址貼至 QuestBoard,並回填鑑定報告:
    • 初心者:提貨單之謎 (理性挑戰)[⚡ 觀念辨析]
      • 1.為什麼導師說物件傳遞的是「提貨單」?
      • 2.如果我把「英雄的心情物件」分享給兩位冒險者,結果其中一位改了心情,另一位看見的心情會受影響嗎?
    • 冒險者:鎧甲變色之謎
      • 1.當你看見 guildArmor 的顏色意外變動時,你覺得那像不像是冒險中「誤拿鑰匙」的慘劇?
  3. 任務完成後,你的名字將永遠標記在公會的英雄榜上!

📚 【圖書館卷軸與前後站連結】