Skip to content

2026-05-28

/ 11 分鐘閱讀

/ Deep JavaScript Foundations v3

NaN:無效數字與正確的檢測方式 ​

本文延續對 JavaScript 特殊值的討論。前幾篇建立了型別系統的基礎,而 NaN 是 number 型別中最容易被誤解的特殊值,也是實務開發中最常產生隱性 bug 的來源之一。

NaN 不是「不是數字」,而是「無效數字」 ​

NaN 的字面意思是 "Not a Number",但這個名稱具有誤導性。更準確的心智模型是:NaN 是一個無效數字(invalid number),一個表示「這個數值運算沒有合法結果」的特殊哨兵值(sentinel value)。

它來自 IEEE 754 浮點數規格,typeof NaN 的回傳值是 "number"。因為 NaN 本身就屬於數值運算的結果空間,只是這個結果是無效的。

js
var myCatsAge = Number('n/a'); // NaN(無法將 "n/a" 轉為數字)
typeof myCatsAge; // "number"

如果把 NaN 理解成「不是數字」,那麼「不是數字的型別是 number」這句話就會顯得矛盾。把它理解成「無效數字」,就完全自然了。

哪些情況會產生 NaN ​

js
var myAge = Number('0o46'); // 38(八進位字串,合法)
var myNextAge = Number('39'); // 39(合法)
var myCatsAge = Number('n/a'); // NaN(無法轉換)

myAge - "my son's age"; // NaN
// 減法運算子只接受數字,JavaScript 嘗試將字串轉為數字
// 字串 "my son's age" 轉換結果為 NaN,任何數字減去 NaN 仍是 NaN

NaN 具有傳染性:任何包含 NaN 的數學運算,結果永遠是 NaN。

NaN 是唯一不等於自身的值 ​

js
myCatsAge === myCatsAge; // false   OOPS!

=== 在這裡說謊了。這不是 JavaScript 的特例,而是 IEEE 754 規格明確規定的行為:NaN 與任何值(包括它自己)都不相等。NaN 是 JavaScript 中唯一一個不具備自我同一性(identity property)的值。

這個特性意味著我們不能用 === 來檢測 NaN,需要專用的工具。

isNaN vs Number.isNaN ​

舊版 isNaN():有問題的設計 ​

js
isNaN(myAge); // false(正確)
isNaN(myCatsAge); // true(正確)
isNaN("my son's age"); // true   OOPS!

isNaN() 在比對前會先將傳入值強制轉型為數字。字串 "my son's age" 本身不是 NaN,但被轉型後變成 NaN,導致回傳 true——這是錯誤的結果。

ES6 的 Number.isNaN():正確的工具 ​

js
Number.isNaN(myCatsAge); // true(正確)
Number.isNaN("my son's age"); // false(正確)

Number.isNaN() 不做任何強制轉型,只嚴格判斷傳入的值是否就是 NaN 本身。這才是現代 JavaScript 中應該使用的檢測方式。

關於「用 0 代替 NaN」的誤區 ​

數字 0 是一個有意義的數學值,用它來表示「沒有合法數值」是錯誤的概念。當一個數值運算無法產生有意義的結果,正確的表達方式是回傳 NaN,而非 0 或 -1(後者是 C 語言時代的歷史遺留做法)。

小結 ​

NaN 是 number 型別下的無效數字,不是一個獨立的型別。它的兩個關鍵特性——不等於自身、在數學運算中具傳染性——決定了它必須用 Number.isNaN() 來正確檢測。舊版的 isNaN() 因為內部強制轉型而行為不可靠,在現代程式碼中應避免使用。

複習 ​

NaN 在 JavaScript 中實際代表什麼? ​

NaN 代表一個無效數字,而非字面上的「不是數字」。它是一個特殊的哨兵值,用來表示無效的數值運算結果,其型別實際上是 'number'。

NaN 在相等性比較上有什麼獨特之處? ​

NaN 是 JavaScript 中唯一一個不等於自身的值,即使使用 === 也是如此。這是由 IEEE 754 規格所定義的行為。

isNaN() 和 Number.isNaN() 有什麼差異? ​

isNaN() 在檢查前會先將值強制轉型為數字,可能對非 NaN 的值回傳 true。Number.isNaN() 則不做任何轉型,嚴格判斷傳入值是否就是 NaN 本身。

涉及 NaN 的數學運算會有什麼行為? ​

任何包含 NaN 的數學運算結果都是 NaN。NaN 會在數學運算中傳播,任何涉及 NaN 的計算都永遠產生 NaN。

在現代 JavaScript 中,檢測一個值是否為 NaN 的建議方式是什麼? ​

使用 Number.isNaN(),它會嚴格判斷值是否為 NaN,不像舊版的 isNaN() 會進行強制轉型。

小測驗 ​

在 JavaScript 中,描述 NaN 最準確的方式是什麼? 無效數字
JavaScript 中哪個方法能可靠地判斷一個值是否為 NaN? Number.isNaN()
NaN 在 JavaScript 中的型別是什麼? number
對包含 NaN 的數學運算求值,結果會是什麼? 回傳 NaN
NaN 在比較行為上有什麼獨特之處? 永遠不等於自身

此文章是 FrontendMasters 上的 Deep JavaScript Foundations, v3 課程筆記

最後更新時間:

Buy Me A Coffee

系列章節 第 5 篇 / 共 69 篇

0 %
MIT Licensed | Copyright © 2025-present Wen-Hsiu's Blog
Photo by Federica Galli on Unsplash