NaN

基线 广泛可用

此功能已得到良好建立,并且可在许多设备和浏览器版本上运行。它自以下时间起在所有浏览器中都可用 2015年7月.

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 语言规范
# sec-value-properties-of-the-global-object-nan

浏览器兼容性

BCD 表仅在浏览器中加载

另请参阅