iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0
JavaScript

React 觀念架構:從js 基礎到Hook 底層邏輯 系列 第 2

DAY 2 傳值還是傳址?從記憶體模型看 React 為什麼強調「不可變性 (Immutability)」

  • 分享至 

  • xImage
  •  

我們建立了 UI = f(state) 的心智模型。但許多新手常遇到這個經典問題:「明明修改了 State 裡的物件,畫面為什麼完全沒更新?」答案不在 React,而在 JavaScript 的記憶體模型。


一、 基本型別 vs. 引用型別

JavaScript 的資料在記憶體中的存放方式不同:

  • 基本型別 (Pass by Value)Number, String, Boolean 等,直接存在 Stack 中。複製時會複製「值」本身,兩者互不影響。
  • 引用型別 (Pass by Reference)Object, Array, Function 等,內容放在 Heap 中,Stack 只存放指向該位址的記憶體指標 (Reference)。
let userA = { name: 'Alice', age: 20 }; // 指向位址 0x001
let userB = userA;                      // 複製指標,同樣指向 0x001

userB.age = 21;        // 修改 0x001 的內容
console.log(userA.age); // 21 (userA 也被改到了)

二、 踩坑實錄:為什麼直改物件 State 畫面不更新?

看這段錯誤寫法:

// 錯誤示範:直接修改原物件 (Mutation)
const [user, setUser] = useState({ name: 'Alice', age: 20 });

const handleBirthday = () => {
  user.age = 21; // 修改原本位址 (0x001) 的內容
  setUser(user); // 傳入同一個記憶體指標 (0x001)
};

React 的檢查機制:Object.is()
setUser 被呼叫時,React 會使用 Object.is(oldValue, newValue) 進行淺比較 (Shallow Compare)。對物件而言,React 只比較記憶體位址:

Object.is(0x001, 0x001) ➔ true

React 認定「資料沒有變」,為了節省效能直接跳過重新渲染 (Skip Re-render)。

三、 正確做法:保持「不可變性 (Immutability)」

不可變性的核心原則:永遠不要直接修改舊資料,而是產生一個全新位址的物件或陣列。

// 正確示範:建立全新的記憶體參考 (New Reference)
const [user, setUser] = useState({ name: 'Alice', age: 20 });

const handleBirthday = () => {
  setUser({
    ...user, // 展開舊屬性
    age: 21  // 覆蓋新屬性
  }); // 產生新物件,位址變為 0x002
};

此時 Object.is(0x001, 0x002) ➔ false,React 判定資料變更,成功觸發 Re-render!

四、 常見資料結構更新速查

https://ithelp.ithome.com.tw/upload/images/20260916/20178516En8gGiAEXr.png


上一篇
Day1 React 是什麼?從 DOM 痛苦時代到「UI 即函數」的核心心智模型
下一篇
DAY 3 閉包 (Closure) 與作用域鏈:理解 Hook State 歷史紀錄的基石
系列文
React 觀念架構:從js 基礎到Hook 底層邏輯 7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言