HOWTO · JavaScript

JavaScript 中的二維陣列

本教程介紹了如何在 JavaScript 中形成二維陣列。

本頁內容

JavaScript 的二維陣列是由各列陣列組成的陣列。已知資料時可使用巢狀陣列字面值;若維度或值來自資料,則可透過迴圈、Array.from() 或 Array.prototype.map() 建立彼此獨立的列。使用兩個索引讀取儲存格:grid[rowIndex][columnIndex]。

JavaScript 中的二維陣列是什麼?

JavaScript 沒有獨立的二維陣列型別。網格是由陣列組成的陣列:外層陣列存放各列,每列則存放其中的儲存格。這種結構可用來表示矩陣、遊戲棋盤或其他列與欄資料。各列長度可以不同,因此若無法確定陣列一定是矩形,請先檢查各列的長度。

陣列索引從零開始。在 grid[1][2] 中,1 選取第二列,2 則選取該列的第三個儲存格。建立各列與填入儲存格是兩個不同步驟:新配置的陣列可能含有未初始化的索引位置,這些位置與設為 null 的儲存格不同。

使用巢狀陣列字面值建立二維陣列

若要建立值已知的固定網格,可將每一列寫成內層陣列:

const grid = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

console.log(grid[0][1]);

每個內層陣列都是不同的列。運算式 grid[0][1] 會選取值 2:第一個索引選取列,第二個索引則選取該列中的儲存格。當完整資料已經備妥時,使用陣列字面值很方便。

使用迴圈建立二維陣列

若維度或儲存格的值要在執行時決定,可使用巢狀迴圈。每次執行外層迴圈時都配置一個新列,接著指派各個儲存格:

const rows = 3;
const columns = 3;
const grid = [];

for (let row = 0; row < rows; row++) {
  grid[row] = [];
  for (let column = 0; column < columns; column++) {
    grid[row][column] = row * columns + column + 1;
  }
}

console.log(grid);

外層迴圈會建立三個彼此獨立的列。內層迴圈則將每列填入 1 到 9 的值。若要讓儲存格以預設值開始,可在內層迴圈中指派,例如 grid[row][column] = 0。

若列之後會變動,請避免使用 Array(rows).fill(Array(columns).fill(0)):fill() 會重複填入同一個列參照,因此修改某列後,每一列相同欄位所顯示的值都會改變。請改為在每次外層迴圈執行時建立新列。

使用 Array.from() 建立二維陣列

Array.from() 可以建立外層陣列,並為每個索引建立一個新列。它的映射回呼函式會收到目前的索引,因此可根據列與欄計算每個儲存格的值:

const rows = 3;
const columns = 3;
const grid = Array.from({ length: rows }, (_, row) =>
  Array.from({ length: columns }, (_, column) => row * columns + column + 1)
);

console.log(grid);

外層呼叫會建立三列;內層呼叫則建立並填入每列的三個值。由於內層的 Array.from() 會針對每個外層索引執行一次,因此每列都是獨立的陣列。若要讓每個儲存格從 0 開始,可將 Array.from({ length: columns }, () => 0) 用作內層呼叫。

使用 Array.prototype.map() 建立二維陣列

map() 會將陣列中已存在的元素轉換成新陣列。請先準備含有實際元素的索引位置,確保回呼函式會對每一列執行;單獨使用 new Array(rows) 會建立稀疏索引位置,而 map() 會略過這些位置。

const rows = 3;
const columns = 3;
const grid = Array.from({ length: rows }, (_, row) => row).map(row =>
  Array.from({ length: columns }, (_, column) => row * columns + column + 1)
);

console.log(grid);

此處先由 Array.from() 建立一個含有列索引的序列,再由 Array.prototype.map() 為每個索引建立一個獨立配置的列。回呼函式也可以傳回填入預設值的列,例如 Array.from({ length: columns }, () => 0)。

初始化及存取二維陣列中的值

若要讀取儲存格,請使用 grid[row][column];若要更新,則透過相同索引指派值,例如 grid[1][2] = 42。對於含有三列、四欄的陣列,有效列索引為 0 到 2,有效欄索引則為 0 到 3。JavaScript 不會強制各列維度相同,因此每列的長度決定了其中有哪些欄索引。

若要初始化網格,並讓所有儲存格使用相同的起始值,請為每個列索引建立新列。例如,Array.from({ length: rows }, () => Array.from({ length: columns }, () => 0)) 會建立彼此獨立的列,並將每個儲存格設為 0。這與含有稀疏索引位置的 new Array(rows) 不同,也不同於使用 fill() 重複同一個內層陣列。

已知值時可使用陣列字面值;需要明確控制建構過程時可使用迴圈;要產生列與儲存格時可使用 Array.from();要轉換已有元素的序列時則可使用 Array.prototype.map()。這四種方式都會產生一般的巢狀陣列;讀取或更新儲存格時,使用相同的列索引後接欄索引即可。