本文 AI 產出,尚未審核

JavaScript 陣列解構(Array Destructuring)

簡介

在日常的前端開發中,我們經常需要從陣列中取出特定的元素,或把多個變數一次性賦值。傳統的做法往往需要寫許多 letvar 或索引存取的程式碼,既冗長又容易出錯。ES6 引入的 陣列解構(Array Destructuring)讓這類操作變得簡潔直觀,只要一行語法就能同時完成多個變數的解構、預設值、剩餘元素的收集等功能。

掌握陣列解構不僅能提升程式碼可讀性,還能減少不必要的臨時變數,對於 函式參數的處理、資料轉換、以及與其他語法(如展開運算子、迭代器)結合 都有相當大的幫助。因此在本單元,我們將深入探討陣列解構的核心概念、常見陷阱與最佳實踐,並透過實務範例說明它在真實專案中的應用方式。


核心概念

1. 基本語法

陣列解構的語法形式是把左側的變數以陣列的形狀寫出,右側則是要解構的來源陣列:

const [a, b] = [1, 2];   // a = 1, b = 2
  • 左側的 [] 表示「我想要從陣列中取出」的結構。
  • 右側的 [] 是實際的來源資料。
  • 位置對應:第一個變數對應第一個元素,依此類推。

小技巧:如果不需要某個位置的元素,只要留空或使用逗號跳過即可。

const [first, , third] = [10, 20, 30]; // first = 10, third = 30

2. 預設值(Default Value)

當來源陣列的某個位置是 undefined,解構的變數會取得 預設值

const [x = 5, y = 10] = [undefined, 20];
console.log(x); // 5
console.log(y); // 20

注意:只有在來源為 undefined 時才會套用預設值,null0'' 等仍保留原值。

3. 剩餘元素(Rest Element)

使用展開運算子 ... 可以一次取得「剩餘」的所有元素,類似於 Array.prototype.slice

const [head, ...tail] = [1, 2, 3, 4];
console.log(head); // 1
console.log(tail); // [2, 3, 4]
  • ... 必須放在左側陣列的 最後一個位置,否則會拋出語法錯誤。

4. 嵌套解構(Nested Destructuring)

解構不只支援一層,對於多維陣列同樣適用:

const [[a, b], [c, d]] = [[1, 2], [3, 4]];
console.log(a, b, c, d); // 1 2 3 4

結合預設值與剩餘元素也可以:

const [first, [second = 0, ...rest] = []] = [10, [20, 30, 40]];
console.log(first);   // 10
console.log(second);  // 20
console.log(rest);    // [30, 40]

5. 在函式參數中的解構

函式的參數列表同樣支援解構,讓呼叫端只需要傳入陣列即可:

function sum([a, b, c]) {
  return a + b + c;
}
console.log(sum([1, 2, 3])); // 6

如果參數有預設值或剩餘元素:

function logger([msg, level = 'info', ...extra]) {
  console.log(`[${level}] ${msg}`, ...extra);
}
logger(['系統啟動', undefined, { user: 'Alice' }]);
// [info] 系統啟動 { user: 'Alice' }

程式碼範例

範例 1:快速交換兩個變數的值

傳統寫法需要暫存變數,而解構只要一行:

let a = 5, b = 9;
[a, b] = [b, a];
console.log(a, b); // 9 5

為什麼好? 省去臨時變數,避免因忘記宣告而產生的 bug。


範例 2:從 API 回傳的陣列中挑選需要的欄位

假設後端回傳 [id, name, email, role],我們只關心 nameemail

function getUserInfo([, name, email]) {
  return { name, email };
}

const apiResult = [101, '王小明', 'xiaoming@example.com', 'admin'];
console.log(getUserInfo(apiResult));
// { name: '王小明', email: 'xiaoming@example.com' }

範例 3:結合 map 與解構一次取出多個欄位

const products = [
  [101, '筆記型電腦', 1200],
  [102, '滑鼠', 35],
  [103, '鍵盤', 80]
];

// 只要取得商品名稱與價格
const simpleList = products.map(([ , name, price]) => ({ name, price }));
console.log(simpleList);
// [{name:'筆記型電腦',price:1200},{name:'滑鼠',price:35},{name:'鍵盤',price:80}]

範例 4:使用剩餘元素收集不確定長度的參數

function concatenate([first, ...rest]) {
  return rest.reduce((acc, cur) => acc + cur, first);
}

console.log(concatenate(['A', 'B', 'C', 'D'])); // "ABCD"

範例 5:解構與預設值防止 undefined 錯誤

function createPoint([x = 0, y = 0] = []) {
  return { x, y };
}

console.log(createPoint([5]));          // { x:5, y:0 }
console.log(createPoint(undefined));   // { x:0, y:0 }

常見陷阱與最佳實踐

陷阱 說明 解決方法
左側變數比來源多 多出的變數會被賦值為 undefined,若未處理可能導致後續錯誤。 使用預設值或在解構前先檢查陣列長度。
左側變數比來源少 多餘的來源元素會被忽略,這在大多數情況是預期行為。 若需要全部元素,記得使用 剩餘元素 (...rest)。
解構嵌套時忘記預設值 深層的 undefined 會導致「Cannot read property of undefined」錯誤。 為每層提供預設值,例如 [[a] = []] = arr
在函式參數解構時忘記提供預設參數 呼叫時傳入 undefined 會拋錯。 為參數本身加上預設值:function f([a, b] = []) {}
使用 ... 於非最後位置 語法錯誤。 確保 ...rest 只出現在左側最後一個位置。

最佳實踐

  1. 保持左側結構與資料來源的可讀性:不要一次寫太多層嵌套,必要時可先拆解成小步驟。
  2. 配合 const 使用:若變數不會再被重新賦值,使用 const 可以防止意外改寫。
  3. 結合其他 ES6 語法:如 for...ofArray.prototype.entries(),可讓迭代與解構同時完成。
  4. 在大型資料轉換時,先做型別檢查:利用 Array.isArraytypeof 讓解構更安全。

實際應用場景

1. 前端 UI 狀態管理

在 React、Vue 或 Svelte 等框架中,常需要從 propsstatestore 中抽取特定值:

// React 範例
const MyComponent = ({ data: [title, description, ...tags] }) => (
  <div>
    <h1>{title}</h1>
    <p>{description}</p>
    <ul>{tags.map(tag => <li key={tag}>{tag}</li>)}</ul>
  </div>
);

2. 處理 CSV / TSV 資料

讀取檔案後每行會得到字串陣列,利用解構直接取得欄位:

const lines = csvText.split('\n');
const header = lines.shift().split(',');

const records = lines.map(line => {
  const [id, name, age] = line.split(',');
  return { id, name, age: Number(age) };
});

3. API 回傳多元資料的快速抽取

如 GraphQL 或 REST 回傳的多層陣列,解構可讓代碼保持簡潔:

async function fetchDashboard() {
  const response = await fetch('/api/dashboard');
  const [summary, recentOrders, stats] = await response.json();
  // summary, recentOrders, stats 直接可用
}

4. 測試資料產生(Test Fixtures)

在單元測試中常需要產生多組測試值,解構配合陣列生成器非常便利:

const cases = [
  [1, 2, 3],
  [0, -1, -1],
  [5, 5, 10]
];

cases.forEach(([a, b, expected]) => {
  test(`add(${a}, ${b}) === ${expected}`, () => {
    expect(add(a, b)).toBe(expected);
  });
});

總結

陣列解構是 ES6 為 JavaScript 帶來的強大語法糖,讓我們在處理陣列資料時能以 宣告式、直觀 的方式一次完成多個變數的賦值、預設值、剩餘元素的收集以及深層嵌套的取值。透過本文的概念說明與實務範例,你應該已掌握:

  • 基本的 [a, b] = arr 語法與跳過元素的技巧。
  • 預設值與剩餘元素的使用情境。
  • 嵌套解構與在函式參數中的應用。
  • 常見的錯誤陷阱以及避免方式。
  • 在 UI 開發、資料轉換、API 處理與測試等領域的實際案例。

在寫程式時,善用解構 不僅能減少冗長代碼,還能提升可讀性與維護性。未來遇到需要從陣列或類似結構中抽取資訊的情境,請先考慮使用解構,讓你的程式碼更簡潔、更安全。祝你在 JavaScript 的旅程中玩得開心、寫得順手!