本文 AI 產出,尚未審核

JavaScript ES6+ 新特性:解構賦值 (Destructuring Assignment)

簡介

在 ES6 之前,從物件或陣列中取出特定值往往需要寫多行冗長的程式碼,例如使用 obj.proparr[0] 逐一取值。解構賦值(Destructuring)則提供了一種宣告式的寫法,讓我們可以在同一行同時把多個屬性或元素「解開」並賦值給變數。

這項語法不僅讓程式碼更簡潔、更具可讀性,也在 React、Node.js、Vue 等現代框架中成為日常開發的必備工具。掌握解構的細節,能讓你在處理 API 回傳資料、函式參數、以及模組匯入時,寫出更安全、可維護的程式。

核心概念

1. 陣列解構

陣列解構的語法形如 let [a, b] = array;,左側的方括號列出「目標變數」的順序,右側則是來源陣列。

// 範例 1:基本陣列解構
const numbers = [10, 20, 30];
let [first, second] = numbers;
console.log(first);   // 10
console.log(second);  // 20
  • 跳過元素:使用逗號保留位置即可。
let [, , third] = numbers;   // 直接取得第三個元素
console.log(third); // 30
  • 設定預設值:當來源陣列缺少對應位置時,可提供備援值。
let [x = 1, y = 2, z = 3] = [5];
console.log(x, y, z); // 5 2 3

2. 物件解構

物件解構使用大括號 {},左側列出欲取出的屬性名稱,右側則是來源物件。

// 範例 2:基本物件解構
const user = { name: "Alice", age: 28, city: "Taipei" };
let { name, age } = user;
console.log(name); // Alice
console.log(age);  // 28
  • 重新命名變數:使用 : 後接新變數名。
let { name: userName, city: location } = user;
console.log(userName); // Alice
console.log(location); // Taipei
  • 預設值:若屬性不存在,會使用預設值。
let { country = "Taiwan" } = user;
console.log(country); // Taiwan

3. 混合解構(陣列裡的物件、物件裡的陣列)

實務上常會碰到結構複雜的資料,例如 API 回傳的 JSON 陣列,每筆資料又是一個物件。

// 範例 3:陣列裡的物件解構
const posts = [
  { id: 1, title: "第一篇", tags: ["js", "es6"] },
  { id: 2, title: "第二篇", tags: ["node", "api"] }
];

let [{ title: firstTitle, tags: [firstTag] }, secondPost] = posts;
console.log(firstTitle); // 第一篇
console.log(firstTag);   // js
console.log(secondPost.title); // 第二篇

4. 函式參數的解構

直接在函式參數位置解構,可讓呼叫端只傳需要的屬性,且避免在函式內重複寫 obj.prop

// 範例 4:函式參數解構 + 預設值
function greet({ name = "訪客", age } = {}) {
  console.log(`哈囉,${name}!您今年 ${age || "未知"} 歲。`);
}

greet({ name: "Bob", age: 35 }); // 哈囉,Bob!您今年 35 歲。
greet({ name: "Cathy" });        // 哈囉,Cathy!您今年 未知 歲。
greet();                         // 哈囉,訪客!您今年 未知 歲。

5. 變數別名與剩餘元素(Rest)

  • 剩餘元素:使用 ...rest 收集未列出的元素或屬性。
// 範例 5:剩餘元素(陣列)
let [head, ...tail] = [1, 2, 3, 4];
console.log(head); // 1
console.log(tail); // [2,3,4]

// 範例 6:剩餘屬性(物件)
let { name, ...others } = user;
console.log(name);   // Alice
console.log(others); // { age: 28, city: 'Taipei' }
  • 深層解構:可直接解構多層巢狀結構。
const config = {
  server: { host: "localhost", port: 8080 },
  db: { user: "admin", password: "secret" }
};

let {
  server: { host, port },
  db: { user }
} = config;
console.log(host, port, user); // localhost 8080 admin

常見陷阱與最佳實踐

陷阱 說明 解決方式
解構時變數未宣告 let {a} = obj; 正確;但直接寫 {a} = obj; 會被視為區塊語句。 必須在左側加上宣告關鍵字(letconstvar)或使用圓括號包住整個表達式。
預設值是 undefined 若來源屬性值本身是 undefined,預設值不會生效。 使用 null 或其他明確的「缺值」判斷,或在解構前先處理資料。
名稱衝突 解構時重新命名變數容易與已有變數同名,造成覆寫。 盡量使用具語意的別名,或在較小的作用域內解構。
深層解構的可讀性 一行寫太多層級會降低可讀性。 只解構必要層級,或分段寫 const {a} = obj; const {b} = a; 以提升清晰度。
剩餘屬性 (...rest) 必須最後 ...rest 只能放在最後,否則會拋出語法錯誤。 確保 ...rest 位於解構列表的最後一個位置。

最佳實踐

  1. 使用 const:除非需要重新指派,盡量用 const 讓變數保持不可變。
  2. 只解構必要屬性:避免一次解構過多,減少不必要的記憶體開銷。
  3. 配合預設值:在處理外部 API 時,為可能缺失的欄位提供預設值,可避免 undefined 帶來的錯誤。
  4. 保持一致的風格:團隊內統一使用解構的寫法(例如參數解構或物件解構),提升程式碼一致性。

實際應用場景

  1. React 組件的 Props 解構
function Card({ title, description, imageUrl }) {
  return (
    <div className="card">
      <img src={imageUrl} alt={title} />
      <h3>{title}</h3>
      <p>{description}</p>
    </div>
  );
}

props 直接解構,使 JSX 內部更乾淨。

  1. Node.js 讀取環境變數
const { DB_HOST = "localhost", DB_PORT = 3306 } = process.env;

快速取得設定,並提供預設值。

  1. 處理 API 回傳的 JSON
async function fetchUser(id) {
  const response = await fetch(`/api/users/${id}`);
  const { data: { name, email, profile: { avatar } = {} } = {} } = await response.json();
  return { name, email, avatar };
}

一次解構多層結構,省去繁瑣的 response.data.profile.avatar

  1. 陣列迭代時同時取得索引
const colors = ["red", "green", "blue"];
colors.forEach((color, index) => {
  const [prev, next] = [colors[index - 1], colors[index + 1]];
  console.log(`Current: ${color}, Prev: ${prev}, Next: ${next}`);
});

結合解構與迭代,讓程式碼更直觀。

總結

解構賦值是 ES6+ 中最具影響力的語法之一,它把 「取值」 的動作變成宣告式的表達,讓程式碼更簡潔、可讀且易於維護。從基本的陣列與物件解構,到函式參數、剩餘元素、深層解構,掌握這些技巧可以大幅提升開發效率,尤其在 React、Node、Vue 等現代框架中更是不可或缺。

在實務開發時,記得遵守 「只解構需要的屬性」「使用 const「提供預設值」 等最佳實踐,並留意常見的語法陷阱。透過適當的解構,你的 JavaScript 程式將變得更清晰、更安全,也更符合現代前端與後端工程的編碼標準。祝你在寫程式的路上,解構出更好的人生