NaN
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
全局属性 NaN
是一个表示非数字的值。
尝试一下
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 * Infinity
、1 ** Infinity
、Infinity / Infinity
、Infinity - Infinity
) - 一个操作数被强制转换为
NaN
的方法或表达式(例如,7 ** NaN
、7 * "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
这样的自我比较。
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
:
isNaN("hello world"); // true
Number.isNaN("hello world"); // false
出于同样的原因,使用 BigInt 值时 isNaN()
会抛出错误,而 Number.isNaN()
不会:
isNaN(1n); // TypeError: Conversion from 'BigInt' to 'number' is not allowed.
Number.isNaN(1n); // false
此外,一些数组方法不能找到 NaN
,而另一些可以。也就是说,查找索引的(indexOf()
、lastIndexOf()
)不能找到 NaN
,而查找值的(includes()
)可以:
const arr = [2, 4, NaN, 12];
arr.indexOf(NaN); // -1
arr.includes(NaN); // true
// 接受正确定义的断言的方法总是能够找到 NaN
arr.findIndex((n) => Number.isNaN(n)); // 2
有关 NaN
及其比较的更多信息,请参阅相等性判断。
明显不同的 NaN 值
可以用不同的二进制表示生成两个都是 NaN
的浮点数,这是因为在 IEEE 754 编码中,任何指数为 0x7ff
且尾数非零的浮点数都是 NaN
。在 JavaScript 中,你可以使用类型化数组来进行位操作。
const f2b = (x) => new Uint8Array(new Float64Array([x]).buffer);
const b2f = (x) => new Float64Array(x.buffer)[0];
// 获取 NaN 的字节表示
const n = f2b(NaN);
const m = f2b(NaN);
// 更改符号位,对于 NaN 而言,这个比特位不重要。
n[7] += 2 ** 7;
// n[0] += 2**7; 对于大端处理器
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]
// 更改第一个比特位,即符号位,对于 NaN 而言,这个比特位不重要。
m[0] = 1;
// m[7] = 1; 对于大端处理器
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
而不测试基数的值。
NaN ** 0 === 1; // true
规范
Specification |
---|
ECMAScript® 2025 Language Specification # sec-value-properties-of-the-global-object-nan |
浏览器兼容性
Report problems with this compatibility data on GitHubdesktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
NaN |
Legend
Tip: you can click/tap on a cell for more information.
- Full support
- Full support