先來看看兔猻的照片,雖然廣義上牠是貓科動物,但狹義來說牠跟家貓是不同屬的(家貓是 Felis(貓屬);兔猻則是 Otocolobus(兔猻屬 )。
(圖片來源:unsplash @GettyImages)
在 JS 裡面也有類似的情況,就是 陣列(Array) 和類陣列(Array-like)。
當對著 類陣列 用.map() 或 .filter() 處理時,會跳出錯誤訊息
Uncaught TypeError: xxx.map is not a function ❌
「奇怪,看起來就是可愛的貓貓,為什麼不能摸?」
(重要:擼貓請徵得貓的同意)
「奇怪,看起來就是陣列,為什麼有些陣列方法不能用?」
陣列就是 JavaScript 用來一次存放多個同類型資料的資料結構。
例如:現在有一個陣列,裡面有白貓、黑貓、橘貓
const catList = ["白貓", "黑貓", "橘貓"];
//可以透過索引(index)取得資料
catList[0]; // "白貓"
catList[1]; // "黑貓"
//現在有幾隻貓
catList.length; // 3
也可以使用陣列的方法:.push()、.map()、.filer()、.forEach()等
檢查是否為陣列(Array)
Array.isArray(catList);
// true
類陣列(Array-like) 是看起來像陣列,但實際上不是陣列的資料。
它通常具有數字索引和 length,因此可以像陣列一樣透過索引取得資料,但不一定能使用陣列的方法。
例如:
const catList = {
0: "白貓",
1: "黑貓",
2: "橘貓",
length: 3
};
catList[0]; // "白貓"
catList.length; // 3
檢查是否為陣列(Array)
Array.isArray(catList);
// false
| 項目 | 陣列 Array | 類陣列 Array-like |
|---|---|---|
| 是不是 Array | ✅ 是 | ❌ 不是 |
| 有索引 | ✅ | 通常有 |
| 有 length | ✅ | 通常有 |
| 可以 arr[0] | ✅ | ✅ |
| 有完整 Array 方法 | ✅ | ❌ 不一定 |
| Array.isArray() | true | false |
當我們在瀏覽器(DOM)中選取多個元素,或是呼叫某些內建語法時,拿到的往往都是 類陣列:
HTMLCollection(例如:document.getElementsByClassName('cat'))特徵:動態集合。完全不能用 .forEach()、.map() 等任何陣列方法。
NodeList(例如:document.querySelectorAll('.cat'))特徵:靜態集合。現代瀏覽器可以用 .forEach()但其他的 .map()、.filter() 依然不能用。
arguments 物件特徵:傳統函式內建用來儲存所有傳入參數的物件,也是標準的類陣列。
// 拿到一組 HTMLCollection (類陣列)
const catElements = document.getElementsByClassName('cat-item');
// 🪄 轉成真正的陣列
const realCatArray = Array.from(catElements);
// 現在可以用 .map()了
const catNames = realCatArray.map(cat => cat.textContent);
(適用於 NodeList 或具備 Iterable 可疊代的類陣列)
const nodeCatList = document.querySelectorAll('.cat-item');
// 用中括號搭配 ... 展開裝進新陣列
const realCatArray = [...nodeCatList];
// 使用 filter 篩選特定條件的貓咪
const blackCats = realCatArray.filter(cat => cat.classList.contains('black'));
個人筆記:
JavaScript 基礎概念 | 什麼是 DOM ?如果網頁是一隻貓
JS DOM | 取得元素的方法:querySelector、querySelectorAll 與傳統選擇器
JS DOM | 選取多個元素時的集合:NodeList vs HTMLCollection 有何不同?