在前端開發與串接 API 處理後端回傳的資料時,經常會遇到原始資料夾雜著 null、undefined 或空值的情況。學會如何正確地進行 JS去除 array 中 null 或空值,能有效避免後續迭代處理時噴出非預期錯誤。想了解基礎原理細節可前往 [JS] 字串將每個字逐一拆解成陣列 與 JS 陣列加總與平均值怎麼算?Array.reduce 初始值設定與物件求和範例 建立觀念。接著我們就直接切入主題,看看如何透過 JavaScript 內建方法高效過濾陣列中的雜訊。
一、 JavaScript 一維陣列去除 null 與空值基本方法
假設你有一筆簡單的一維陣列資料,長得像這樣:
const a = [
null,
null,
1,
2,
3,
null,
10
];
如果你希望將該資料中的 null 清除,可以透過 filter 搭配條件判斷來達成:
a.filter(e => e);
由於在 JavaScript 中,null、undefined、0、"" (空字串) 等值在進行條件判斷時都會被強制轉型為 false (Falsy 值)。如果你的目標是要過濾掉這些常見的空值,也可以直接簡化傳入 Boolean 建構函式,利用這個特性來達到資料過濾的目的:
a.filter(Boolean);
二、 多維陣列與複雜巢狀結構的清理策略
當資料結構再複雜一點,變成含有巢狀陣列的多維資料時,單純對一維陣列使用的 filter 就無法完全清除內層的 null。這時你可以結合 map 與條件判斷來處理:
const a = [
null,
null,
[
{a:1, b:2},
null,null,null,null,
5,
],
[
{a:11, b:22},
10,
],
[
{a:111, b:222},
123,
456,
null,null,
5,
null,null,
],
null,
10
];
a.filter(Boolean).map(e => Array.isArray(e) ? e.filter(Boolean) : e);
在寫這類邏輯時,整體的思路是先對外層做一次過濾,再透過 map 走訪每個元素,並針對子層資料再次進行過濾。
三、 處理三維以上深層巢狀陣列的遞迴解法
當巢狀結構不只兩層,而是擴展到三維甚至更深的未預期深度時,單次使用的 map 搭配 filter 就無法完全清除所有的 null 空值。面對這種動態且深層的巢狀結構,最妥善的做法是改用遞迴(Recursion)函式來逐層深入清理。
透過遞迴,函式會自我呼叫來檢查每一個元素:只要遇到陣列就繼續往內遞迴過濾,直到確認最底層的非陣列資料為止,同時一併將當前層級的 null 與 Falsy 值透過 filter(Boolean) 排除。
const deepRemoveNull = (data) => {
// 如果不是陣列,直接回傳原值
if (!Array.isArray(data)) {
return data;
}
// 先過濾掉當前層級的空值,並對每個元素進行遞迴處理
return data
.filter(Boolean)
.map(item => deepRemoveNull(item));
};
const deepData = [
null,
[
1,
null,
[
2,
null,
[3, null, 4]
]
],
10
];
console.log(deepRemoveNull(deepData));
// 輸出結果:[ [ 1, [ 2, [ 3, 4 ] ] ] ], 10 ]
四、 實務踩坑、注意事項與封裝共用函式
在實際專案開發中處理陣列過濾時,有幾個常見的邊界條件與維護要點需要特別留意:
- 型態防護:在對元素執行操作前,必須先透過
Array.isArray()判斷該資料是否為陣列,否則當遇到物件、字串或數字時呼叫過濾方法便會產生執行階段錯誤。 - Falsy 值誤判:使用
Boolean篩選會一併過濾掉0、false與空字串""。如果你的業務邏輯中0是合法且需要保留的有效數值,請改用明確的比較判斷式(例如e !== null && e !== undefined)來取代filter(Boolean)。 - 共用函式封裝:假設你在專案中有多個地方都需要用到這項清理邏輯,建議可以將過濾動作獨立封裝成共用函式,方便後續直接呼叫:
const a = [
null,
null,
[
{a:1, b:2},
null,null,null,null,
5,
],
[
{a:11, b:22},
10,
],
[
{a:111, b:222},
123,
456,
null,null,
5,
null,null,
],
null,
10
];
const removeNull = (data) => {
return Array.isArray(data) ? data.filter(Boolean) : data;
};
removeNull(a).map(e => removeNull(e));
五、 常見問題 (Q&A)
Q1:使用 filter(Boolean) 會不小心把數字 0 或空字串 "" 濾掉嗎?該怎麼辦?
解答:會的。Boolean 建構函式在 JavaScript 中會將所有 Falsy 值(包含 null、undefined、0、""、false、NaN)一併視為無效值並過濾掉。如果你的業務邏輯中,0 或空字串是合法的有效數值,請避免直接使用 filter(Boolean),改用明確的條件判斷式(例如:e => e !== null && e !== undefined)來精準過濾 null 與 undefined。
Q2:如果陣列內夾雜物件(Object),直接用 filter(Boolean) 會把物件刪掉嗎?
解答:不會。在 JavaScript 中,任何非空物件與陣列(包含 {}、[])在進行布林轉型時皆為 truthy。因此,當陣列中夾雜物件時,filter(Boolean) 會保留這些物件,只會剔除真正的 null 或 undefined。若需同時過濾物件內部的空值屬性,則需要額外撰寫遞迴函式或屬性檢查邏輯。
Q3:後端 API 回傳的資料結構不固定,有時候是 null 而不是陣列,該怎麼預防前端直接當機?
解答:在對後端回傳的資料呼叫 .filter() 或其他陣列方法前,務必先進行防禦性檢查。最常見的做法是利用預設參數或邏輯運算子確保其型態為陣列,例如寫成 (response.data || []).filter(Boolean),或者透過前文提到的 Array.isArray() 函式先行攔截,避免因型態錯誤導致畫面直接白屏噴錯。
發佈留言