NaN

NaN 全局属性是表示非数字的值。

¥The NaN global property is a value representing Not-A-Number.

Try it

¥Value

Number.NaN 相同的数值。

¥The same number value as Number.NaN.

Property attributes of NaN
Writable no
Enumerable no
Configurable no

描述

¥Description

NaN 是全局对象的属性。换句话说,它是全局范围内的变量。

¥NaN is a property of the global object. In other words, it is a variable in global scope.

在现代浏览器中,NaN 是不可配置、不可写的属性。即使情况并非如此,也请避免覆盖它。

¥In modern browsers, NaN is a non-configurable, non-writable property. Even when this is not the case, avoid overriding it.

返回 NaN 的操作有五种不同类型:

¥There are five different types of operations that return NaN:

  • 数字转换失败(例如 parseInt("blabla")Number(undefined) 等显式转换,或 Math.abs(undefined) 等隐式转换)
  • 结果不是实数的数学运算(例如 Math.sqrt(-1)
  • 不定形式(例如 0 * Infinity1 ** InfinityInfinity / InfinityInfinity - Infinity
  • 其操作数被强制为 NaN 的方法或表达式(例如 7 ** NaN7 * "blabla") - 这意味着 NaN 具有传染性
  • 其他将无效值表示为数字的情况(例如无效的 日期 new Date("blabla").getTime()"".charCodeAt(1)

NaN 及其行为不是 JavaScript 发明的。它在浮点运算中的语义(包括 NaN !== NaN)由 IEEE 754 指定。NaN 的行为包括:

¥NaN and its behaviors are not invented by JavaScript. Its semantics in floating point arithmetic (including that NaN !== NaN) are specified by IEEE 754. NaN's behaviors include:

  • 如果数学运算涉及 NaN(但不涉及 按位运算),则结果通常也是 NaN。(参见下面的 counter-example。)
  • NaN 是任何关系比较(><>=<=)的操作数之一时,结果始终为 false
  • NaN 将不相等(通过 ==!====!==)与任何其他值进行比较,包括与另一个 NaN 值进行比较。

NaN 也是 JavaScript 中的 falsy 值之一。

¥NaN is also one of the falsy values in JavaScript.

示例

¥Examples

针对 NaN 进行测试

¥Testing against NaN

要判断一个值是否为 NaN,请使用 Number.isNaN()isNaN() 最清楚地确定一个值是否为 NaN,或者,由于 NaN 是唯一与自身比较不等于的值,因此你可以像 x !== x 一样执行自我比较。

¥To tell if a value is NaN, use Number.isNaN() or isNaN() to most clearly determine whether a value is NaN — or, since NaN is the only value that compares unequal to itself, you can perform a self-comparison like 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

¥However, do note the difference between isNaN() and Number.isNaN(): the former will return true if the value is currently NaN, or if it is going to be NaN after it is coerced to a number, while the latter will return true only if the value is currently NaN:

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

出于同样的原因,使用 BigInt 值将引发 isNaN() 错误,而 Number.isNaN() 则不会:

¥For the same reason, using a BigInt value will throw an error with isNaN() and not with Number.isNaN():

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

此外,某些数组方法无法找到 NaN,而其他数组方法可以。即,索引查找器(indexOf()lastIndexOf())无法找到 NaN,而价值查找器(includes())可以:

¥Additionally, some array methods cannot find NaN, while others can. Namely, the index-finding ones (indexOf(), lastIndexOf()) cannot find NaN, while the value-finding ones (includes()) can:

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 及其比较的更多信息,请参阅 平等比较和相同

¥For more information about NaN and its comparison, see Equality comparison and sameness.

明显不同的 NaN 值

¥Observably distinct NaN values

NaN 与其自身不相等是有动机的。可以产生两个具有不同二进制表示形式的浮点数,但都是 NaN,因为在 IEEE 754 编码 中,任何具有指数 0x7ff 和非零尾数的浮点数都是 NaN。在 JavaScript 中,你可以使用 类型数组 进行位级操作。

¥There's a motivation for NaN being unequal to itself. It's possible to produce two floating point numbers with different binary representations but are both NaN, because in IEEE 754 encoding, any floating point number with exponent 0x7ff and a non-zero mantissa is NaN. In JavaScript, you can do bit-level manipulation using typed arrays.

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

¥Silently escaping NaN

NaN 通过数学运算传播,因此通常在计算结束时测试 NaN 一次以检测错误情况就足够了。NaN 被静默转义的唯一情况是使用指数为 0exponentiation 时,它会立即返回 1 而无需测试基值。

¥NaN propagates through mathematical operations, so it's usually sufficient to test for NaN once at the end of calculation to detect error conditions. The only case where NaN gets silently escaped is when using exponentiation with an exponent of 0, which immediately returns 1 without testing the base's value.

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

规范

Specification
ECMAScript Language Specification
# sec-value-properties-of-the-global-object-nan

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看