目次 1 JavaScript undefined 完整指南:判斷、與 null 的差異及安全處理方式1.1 1. 先理解 undefined 代表什麼1.1.1 1.1 常見出現情境1.1.2 1.2 undefined 不是例外訊號1.2 2. undefined、null 與其他假值的差異1.2.1 2.1 預設值應使用 ?? 還是 ||1.2.2 2.2 比較時保持意圖清楚1.3 3. 安全判斷 undefined 的三種方式1.3.1 3.1 宣告過的變數使用 === undefined1.3.2 3.2 名稱可能未宣告時使用 typeof1.3.3 3.3 判斷欄位存在與否時使用 Object.hasOwn()1.4 4. 在瀏覽器程式中避免屬性存取錯誤1.4.1 4.1 用 optional chaining 處理可選路徑1.4.2 4.2 操作 DOM 前先確認元素1.5 5. Fetch API:先驗證 HTTP,再驗證資料形狀1.5.1 5.1 除錯順序1.6 6. 實務檢查清單1.7 7. 常見問題1.7.1 undefined 與 null 相同嗎?1.7.2 應該使用 value === undefined 還是 typeof value === "undefined"?1.7.3 可以用 == null 判斷 undefined 嗎?1.7.4 沒有屬性與屬性值為 undefined 如何區分?1.7.5 optional chaining 能避免所有 undefined 錯誤嗎?JavaScript undefined 完整指南:判斷、與 null 的差異及安全處理方式undefined 是 JavaScript 用來表示「此處目前沒有值」或「找不到該屬性」的原始值。它本身不是錯誤;真正容易出錯的是把它當成物件或字串繼續存取。本指南以瀏覽器 JavaScript 為範圍,說明如何辨識 undefined、保留有效的假值,以及在 DOM 和 Fetch API 邊界安全地驗證資料。
1. 先理解 undefined 代表什麼已宣告但尚未指派值的變數是 undefined。讀取不存在的物件屬性、略過函式引數,或呼叫沒有 return 值的函式,也會得到 undefined。這些行為可參考 MDN 的 undefined 說明。
1.1 常見出現情境let userName;
console.log(userName); // undefined
const user = { name: "Lin" };
console.log(user.email); // undefined
function writeLog() {
console.log("loaded");
}
console.log(writeLog()); // undefined
請區分「值是 undefined」和「識別字根本未宣告」。例如直接讀取未宣告的 missingName 會拋出 ReferenceError;若該名稱可能不存在,應以 typeof 先檢查。
1.2 undefined 不是例外訊號選填欄位、尚未完成的初始載入,或沒有搜尋結果時,undefined 可以是正常狀態。應在資料進入下一層處理前決定欄位是必填、選填,還是可套用預設值;不要讓這個決定散落在每個屬性存取點。
2. undefined、null 與其他假值的差異在布林條件中,undefined、null、空字串、false 與 0 都可能被視為假值,但它們的業務意義不同。
值通常表示的狀態Boolean(值)undefined尚未設定或屬性不存在falsenull程式刻意表示沒有值false""已設定為空文字falsefalse已指定布林值為否false0已指定數值零false2.1 預設值應使用 ?? 還是 ||若只有 null 或 undefined 才要啟用預設值,使用空值合併運算子 ??。|| 會把所有假值都改成預設值,可能不符合設定值的原意。
const options = { retryCount: 0, label: "", enabled: false };
console.log(options.retryCount ?? 3); // 0
console.log(options.retryCount || 3); // 3
2.2 比較時保持意圖清楚null == undefined 的結果為 true,但 null === undefined 為 false。若設計上要把兩者一起視為「缺值」,value == null 可以明確表達這個有限的例外;若只要判斷 undefined,則使用 value === undefined。
3. 安全判斷 undefined 的三種方式3.1 宣告過的變數使用 === undefined對已知存在的變數或物件屬性,嚴格比較最直接,也不會把 0、空字串或 false 誤判為缺值。
const response = { id: 10 };
if (response.name === undefined) {
console.log("回應沒有 name 欄位");
}
3.2 名稱可能未宣告時使用 typeoftypeof 對未宣告的識別字不會拋出例外,適合用在由其他指令碼或執行環境提供的可選全域設定。
if (typeof analyticsConfig === "undefined") {
console.log("分析設定未載入");
}
一般的區域變數和函式引數不需要這種防護;採用 === undefined 會更容易讀出程式意圖。
3.3 判斷欄位存在與否時使用 Object.hasOwn()「沒有欄位」和「欄位存在但值是 undefined」是不同狀態。兩者以點記法讀取都會得到 undefined,需要時可用 MDN 的 Object.hasOwn() 文件 所描述的 Object.hasOwn() 加以區分。
const absent = {};
const present = { label: undefined };
console.log(absent.label === undefined); // true
console.log(present.label === undefined); // true
console.log(Object.hasOwn(absent, "label")); // false
console.log(Object.hasOwn(present, "label")); // true
4. 在瀏覽器程式中避免屬性存取錯誤JavaScript 的 undefined、null 與缺少屬性在 DOM 或 API 使用前的安全檢查流程。4.1 用 optional chaining 處理可選路徑?. 會在左側為 null 或 undefined 時停止屬性存取,並產生 undefined。其語義與限制可參考 MDN 的 optional chaining 文件。
const apiResponse = { user: undefined };
const city = apiResponse.user?.address?.city;
console.log(city); // undefined
這是處理可選資料的工具,不是修復資料的工具。若 user.id 是畫面必需資料,請在邊界顯示錯誤、重試或停止流程,而非只用 ?. 掩蓋缺漏。
4.2 操作 DOM 前先確認元素document.querySelector() 找不到相符元素時會傳回 null。只在部分頁面存在的元素,應在取得後立即分支;這與 undefined 的處理不同,因為 DOM API 的「找不到」契約是 null。
const notice = document.querySelector(".notice");
if (notice) {
notice.textContent = "已儲存";
}
如果元素在該頁理應必定存在,較合適的策略是明確回報初始化錯誤,讓模板問題能被修正,而不是靜默略過。
5. Fetch API:先驗證 HTTP,再驗證資料形狀fetch() 成功完成網路請求不等於 HTTP 狀態成功,也不等於 JSON 含有必填欄位。應依序確認 response.ok、解析結果與必要資料。關於 fetch() 的回應行為,請參考 MDN 的 Fetch API 文件。
async function loadUserName() {
const response = await fetch("/api/user");
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
if (data.name === undefined) {
throw new Error("API response does not include name");
}
return data.name;
}
將 API 欄位分成必填與選填:選填欄位可提供合理的顯示預設值;必填欄位缺失時,應向使用者呈現可理解的錯誤、記錄診斷資訊,並檢查前後端的資料契約。
5.1 除錯順序遇到 Cannot read properties of undefined 時,可依下列順序縮小範圍:
從堆疊追蹤確認是哪一個變數與哪個屬性被讀取。在問題前記錄值及預期的資料形狀,例如 console.log({ value })。在瀏覽器 Network 面板確認 API 狀態碼和回應內容。若涉及非同步流程,確認 await 或狀態更新已在使用資料前完成。回到規格,決定缺值屬於必填錯誤、選填狀態或可接受的預設值。 6. 實務檢查清單是否分清楚 undefined、未宣告名稱,以及 API 回傳的 null?是否避免用 !value 把 0、空字串和 false 一律當作未設定?是否在只需替換空值時選擇 ??,而不是 ||?是否在「欄位是否存在」很重要時使用 Object.hasOwn()?是否在 DOM、API 與非同步邊界驗證必填資料?是否避免用 optional chaining 隱藏必填資料遺失? 7. 常見問題
undefined 與 null 相同嗎?不相同。undefined 通常表示尚未設定或找不到值;null 則是程式刻意表示沒有值。兩者以嚴格比較判斷時不同。
應該使用 value === undefined 還是 typeof value === "undefined"?對已宣告的變數或屬性使用 value === undefined。只有在名稱本身可能未宣告時,才使用 typeof value === "undefined"。
可以用 == null 判斷 undefined 嗎?可以,但僅限意圖是同時接受 null 與 undefined 的情況。若只要判斷 undefined,請使用 === undefined。
沒有屬性與屬性值為 undefined 如何區分?兩者讀取屬性時都會得到 undefined。需要判斷屬性本身是否存在時,使用 Object.hasOwn(object, "key")。
optional chaining 能避免所有 undefined 錯誤嗎?不能。它可避免可選路徑上的屬性存取例外,但不會補齊遺失資料;必填資料缺失時仍要設計錯誤處理或重試流程。