5. Number
ECMAScript 有两种内置的数值类型:Number 和 BigInt
按照 ECMAScript 标准的规定,JavaScript 中的所有算术都要使用双精度浮点算术来完成。
1. 通用知识
关于双精度浮点数,需要理解以下内容:
浮点数的四类常量:最大最小正数、最大最小安全整数、最小间隔、特殊值
内容较多,所以分成多篇在《计算机基础》的浮点数章节中进行详细的介绍。
2. Number 类型
JavaScript 里的 Number 类型是一个双精度 64-bit 二进制格式 IEEE 754 值,这意味着它能表示小数,但在存储上会有一些限制,比如算术上需要四舍五入、精度上只保留大约 17 个有效数字。
a double-precision 64-bit binary format IEEE 754 value
2.1 浮点数
在 JavaScript 代码中,字面量 35
本质上是个浮点数而不是整数,在日常使用中是没有单独的整数类型的。现在有了个 BigInt 类型,但它并不是为了在日常使用中取代 Number 的。
除了表示浮点数之外,Number 类型还有三个符号值:+Infinity
、-Infinity
和 NaN
(Not a Number)。
2.2 范围
能存储 [, ] 之间的正浮点数和 [-, -] 之间的负浮点数:超出此范围的数值会被替换成
±Infinity
和±0
但只能安全地存储 ±(- 1) 范围内的整数:超出此范围的数值,将不能被安全地表示
关于这两个范围涉及的具体值的解释和相关常量,详见双精度浮点数中的四类常量。
2.3 NaN
NaN
NaN
,Not a Number,非数值。
当算术运算的结果不能表示为数值时,通常会遇到 NaN
。以下五类操作会返回 NaN
:
无法解析的数值,比如
parseInt('hello')
,Number(undefined)
结果不是实数的数学运算,比如
Math.sqrt(-1)
操作数是
NaN
,比如7**NaN
不确定形式,比如
0*Infinity
,undefined+undefined
对于不是加法的运算,只要涉及到了字符串就会返回
NaN
,比如'foo'/2
NaN
是全局对象上的一个属性。在现代浏览器中,NaN
是不可配置、不可写的。
NaN = 'test';
console.log(NaN); // NaN,值未变
通常,我们很少在程序中使用 NaN
变量或是去覆盖它,当然也不建议这么做。
2.4 字面量表示
Number 可以用字面量表示,比如 1e3
, 08
, 0755
, 0o755
, 0b111
, 0x7fe
等。
这部分内容,详见数值的字面量表示。
3. Number 对象
Number 对象是 Number 原始值的对象包装器,用来表示和操作数值类型。
3.1 构造器
new Number()
返回 Number 对象,搭配 new 关键字作为构造函数用Number()
返回 Number 数值,直接当函数用可做类型转换,如果不能转换就返回NaN
将 Number()
作为函数使用,很常见。如下:
// 类型转换
Number("123"); // 123
Number("0b111"); // 7
Number("0o111"); // 73
Number("0x111"); // 273
Number("unicorn"); // NaN
Number(undefined); // NaN
Number("123"); // 123
Number("123") === 123; // true
Number("12.3"); // 12.3
Number("12.00"); // 12
Number("123e-1"); // 12.3
Number(""); // 0
Number(null); // 0
Number("0x11"); // 17
Number("0b11"); // 3
Number("0o11"); // 9
Number("foo"); // NaN
Number("100a"); // NaN
Number("-Infinity"); // -Infinity
将 Number()
加关键词 new
当做构造函数使用,很少见,也不推荐。原因如下:
// new Number() 很少使用
let numObj = new Number(35);
numObj == 35; // true
numObj === 35; // false,和字面量数字不全等,因为类型不同
typeof numObj === 'object'; // false
typeof 35 === 'number'; // true
3.2 静态属性
最大正数和最小正数
Number.MAX_VALUE
可表示的最大正数Number.MIN_VALUE
可表示的最小正数,即最接近零的正数(实际上并不为零)
最大安全整数和最小安全整数
Number.MAX_SAFE_INTEGER
最大安全整数, - 1Number.MIN_SAFE_INTEGER
最小安全整数,-( - 1)
正负无穷大(溢出时返回)
Number.NEGATIVE_INFINITY
表示负无穷大的特殊值Number.POSITIVE_INFINITY
表示无穷大的特殊值
Number.EPSILON
两个可表示的数值之间的最小间隔Number.NaN
关于以上静态属性的含义和值,详见双精度浮点数中的四类常量。
最后一个,Number.prototype
允许向 Number 对象添加属性。
3.3 静态方法
布尔判断
Number.isNaN()
Number.isFinite()
Number.isInteger()
Number.isSafeInteger()
类型转换
Number.parseFloat(string)
Number.parseInt(string, [radix])
3.4 实例方法
Number.prototype.xxx
3.4.1 通用方法
valueOf()
返回原始值toString([radix])
返回以指定基数表示的字符串toLocaleString([locales [, options]])
3.4.2 常用操作
toPrecision(precision)
返回指定精度的数值字符串toFixed(digits)
小数点后保留固定位数(using fixed-point notation,使用定点符号)toExponential(fractionDigits)
返回以指数表示法表示的数值字符串
4. 注意事项
4.1 判断一个值是否为 NaN
NaN
NaN
是 JavaScript 中唯一不等于自身的值。
NaN == NaN; // false
NaN === NaN; // false
当我们想判断一个值是不是 NaN
的时候,可以使用 isNaN()
和 Number.isNaN()
,或者是进行下自我比较,因为只有 NaN
不等于自身。代码如下:
isNaN(NaN); // true
isNaN(Number.NaN); // true
Number.isNaN(NaN); // true
Number.isNaN(Number.NaN); // true
// 和自己比较
function myIsNaN(x) {
return x !== x;
}
myIsNaN(1); // false
myIsNaN(NaN); // true
myIsNaN(Number.NaN); // true
4.2 isNaN()
与 Number.isNaN()
isNaN()
与 Number.isNaN()
它两的区别在于:当一个非 NaN
的值经过强制类型转换之后值是 NaN
时,isNaN()
是返回 true,而 Number.isNaN()
是返回 false。如下:
isNaN('hello'); // true
Number.isNaN('hello'); // false
也就是说 Number.isNaN()
只有当值是 NaN
时才会返回 true。
基于同样的原因,当参数是个 BigInt 值的时候,它两的表现也不一样。如下:
isNaN(1n); // TypeError: Cannot convert a BigInt value to a number
Number.isNaN(1n); // false
此外,数组的有些方法找不到 NaN
值,而有些方法可以。比如:
let scores = [80, 90, NaN, 100];
scores.indexOf(NaN); // -1 未找到
scores.includes(NaN); // true 能找到
scores.findIndex(x => Number.isNaN(x)); // 2
4.3 判断是否相等
对于非整数的计算结果,不能用 ==
和 ===
进行比较,正确的比较方法是检测相差的微小值。比如:
0.1 + 0.2 == 0.3; // false
0.1 + 0.2 === 0.3; // false
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON; // true
5. 主要参考
Last updated