NaN

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2015 年 7 月⁩以來,各瀏覽器均已提供此特性。

NaN 全域性屬性表示“非數字”(Not-A-Number)的值。

試一試

function sanitize(x) {
  if (isNaN(x)) {
    return NaN;
  }
  return x;
}

console.log(sanitize("1"));
// Expected output: "1"

console.log(sanitize("NotANumber"));
// Expected output: NaN

Number.NaN 具有相同的數值。

NaN 的屬性特性
可寫
可列舉
可配置

描述

NaN全域性物件的屬性。換句話說,它是全域性作用域中的一個變數。

在現代瀏覽器中,NaN 是一個不可配置、不可寫的屬性。即使在不是這種情況時,也要避免覆蓋它。

有五種不同型別的操作會返回 NaN

  • 失敗的數字轉換(例如,顯式轉換,如 parseInt("blabla")Number(undefined);或隱式轉換,如 Math.abs(undefined)
  • 結果不是實數的數學運算(例如,Math.sqrt(-1)
  • 不確定形式(例如,0 * Infinity1 ** InfinityInfinity / InfinityInfinity - Infinity
  • 其運算元是或被強制轉換為 NaN 的方法或表示式(例如,7 ** NaN7 * "blabla")——這意味著 NaN 具有傳染性
  • 其他需要將無效值表示為數字的情況(例如,無效的 Date new Date("blabla").getTime()"".charCodeAt(1)

NaN 及其行為並非由 JavaScript 發明。其在浮點算術中的語義(包括 NaN !== NaN)由 IEEE 754 規範。NaN 的行為包括:

  • 如果 NaN 參與數學運算(但不是位移操作),結果通常也是 NaN。(請參閱下面的反例。)
  • NaN 是任何關係比較(><>=<=)的運算元之一時,結果始終為 false
  • NaN 與任何其他值(包括另一個 NaN 值)進行比較時,都不相等(透過 !====!==)。

NaN 也是 JavaScript 中的假值之一。

示例

測試 NaN

要判斷一個值是否為 NaN,請使用 Number.isNaN()isNaN() 以最清晰地確定一個值是否為 NaN——或者,由於 NaN 是唯一一個與自身不相等的值,你可以執行諸如 x !== x 的自比較。

js
NaN === NaN; // false
Number.NaN === NaN; // false
isNaN(NaN); // true
isNaN(Number.NaN); // true
Number.isNaN(NaN); // true

function valueIsNaN(v) {
  return v !== v;
}
valueIsNaN(1); // false
valueIsNaN(NaN); // true
valueIsNaN(Number.NaN); // true

但是,請注意 isNaN()Number.isNaN() 之間的區別:前者在值當前是 NaN,或者在被強制轉換為數字後將是 NaN 時返回 true,而後者僅在值當前是 NaN 時才返回 true

js
isNaN("hello world"); // true
Number.isNaN("hello world"); // false

出於同樣的原因,使用 BigInt 值會透過 isNaN() 丟擲錯誤,但不會透過 Number.isNaN() 丟擲錯誤。

js
isNaN(1n); // TypeError: Conversion from 'BigInt' to 'number' is not allowed.
Number.isNaN(1n); // false

此外,一些陣列方法無法找到 NaN,而另一些則可以。具體來說,查詢索引的方法(indexOf()lastIndexOf())無法找到 NaN,而查詢值的方法(includes())可以。

js
const arr = [2, 4, NaN, 12];
arr.indexOf(NaN); // -1
arr.includes(NaN); // true

// Methods accepting a properly defined predicate can always find NaN
arr.findIndex((n) => Number.isNaN(n)); // 2

有關 NaN 及其比較的更多資訊,請參閱相等性比較和同一性

可觀察到的不同 NaN 值

可以生成兩個具有不同二進位制表示但都是 NaN 的浮點數,因為在 IEEE 754 編碼中,任何指數為 0x7ff 且非零尾數的浮點數都是 NaN。在 JavaScript 中,你可以使用型別化陣列進行位級操作。

js
const f2b = (x) => new Uint8Array(new Float64Array([x]).buffer);
const b2f = (x) => new Float64Array(x.buffer)[0];
// Get a byte representation of NaN
const n = f2b(NaN);
const m = f2b(NaN);
// Change the sign bit, which doesn't matter for NaN
n[7] += 2 ** 7;
// n[0] += 2**7; for big endian processors
const nan2 = b2f(n);
console.log(nan2); // NaN
console.log(Object.is(nan2, NaN)); // true
console.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]
console.log(f2b(nan2)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 255]
// Change the first bit, which is the least significant bit of the mantissa and doesn't matter for NaN
m[0] = 1;
// m[7] = 1; for big endian processors
const nan3 = b2f(m);
console.log(nan3); // NaN
console.log(Object.is(nan3, NaN)); // true
console.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]
console.log(f2b(nan3)); // Uint8Array(8) [1, 0, 0, 0, 0, 0, 248, 127]

靜默逃逸的 NaN

NaN 在數學運算中會傳播,因此通常只需在計算結束時測試一次 NaN 即可檢測錯誤情況。NaN 唯一會靜默逃逸的情況是使用冪運算且指數為 0 時,它會立即返回 1,而不測試底數的值。

js
NaN ** 0 === 1; // true

規範

規範
ECMAScript® 2026 語言規範
# sec-value-properties-of-the-global-object-nan

瀏覽器相容性

另見