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 * Infinity
、1 ** Infinity
、Infinity / Infinity
、Infinity - Infinity
) - 其操作数被强制为
NaN
的方法或表达式(例如7 ** NaN
、7 * "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.
示例
针对 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
.
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
:
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()
:
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:
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.
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
被静默转义的唯一情况是使用指数为 0
的 exponentiation 时,它会立即返回 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.
NaN ** 0 === 1; // true
规范
Specification |
---|
ECMAScript Language Specification # sec-value-properties-of-the-global-object-nan |
浏览器兼容性
BCD tables only load in the browser
也可以看看
¥See also