ES6学习二
数值的扩展
1. 二进制、八进制和十六进制表示法
1.1 不同进制的表示
在js中,10进制是不需要任何特殊表示方法的,但是2进制与8进制和16进制则需要特殊表示。
在以前前,JS表示16进制的数字,需要以0x(或0X)开头
0x00 === 0 // true
0x0A === 10 // true
0x0F === 15 // true
0x10 === 16 // true
表示8进制的数字,需要以0开头
000 === 0 // true
007 === 7 // true
010 === 8 // true
表示2进制的数字,需要以0b(或0B)开头
0b00 === 0 // true
0b01 === 1 // true
0b10 === 2 // true
但是8进制这种以0开头的表示方法容易引起歧义,有的浏览器会当作10进制来解析,所以从 ES5 开始,在严格模式之中,八进制就不再允许使用前缀0表示,ES6进一步明确,要使用前缀0o(或0O)表示
0o00 === 0 // true
0o07 === 7 // true
0o10 === 8 // true
1.2 不同进制转换
- 使用
Number方法可以将不同进制的数值转为十进制的数值
Number(0x10) // 16
Number(0O10) // 8
Number(0b10) // 2
- 使用
toString()方法转化成任意进制的字符串(得到的结果不带前缀)
0b11111.toString(2) === '1111'
0b11111.toString(8) === '37'
// 默认转为10进制
0b11111.toString() === '31'
0b11111.toString(16) === '1f'
// 非常规进制也可以转换
0b11111.toString(6) === '51'
2. Number对象的方法
2.1 Number.isFinite(), Number.isNaN()
ES6 在Number对象上,新提供了Number.isFinite()和Number.isNaN()两个方法。
它们与传统的全局方法isFinite()和isNaN()的区别在于,传统方法先调用Number()将非数值的值转换为数值,再进行判断,而这两个新方法只对数值有效。
Number.isFinite()用来检查一个数值是否为有限的(finite),即不是Infinity。同时,如果参数类型不是数值,Number.isFinite一律返回false。
Number.isFinite(15); // true
Number.isFinite(0.8); // true
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite('foo'); // false
Number.isFinite('15'); // false
Number.isFinite(true); // false
Number.isNaN()用来检查一个值是否为NaN。同时,如果参数类型不是NaN,Number.isNaN一律返回false。
Number.isNaN(NaN) // true
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true
2.2 和安全整数和Number.isInteger(),Number.isSafeInteger()
由于 JavaScript 采用 IEEE 754 标准,数值存储为64位双精度格式,数值精度最多可以达到 53 个二进制位(1 个隐藏位与 52 个有效位)。即JavaScript 能够准确表示的整数范围在-2^53到2^53之间(不含两个端点),如果数值的精度超过这个限度,第54位及后面的位就会被丢弃。
Math.pow(2, 53) // 9007199254740992
9007199254740992 // 9007199254740992
9007199254740993 // 9007199254740992 (精度丢失)
Math.pow(2, 53) === Math.pow(2, 53) + 1
// true
- ES6 引入了
Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。
Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1
// true
Number.MAX_SAFE_INTEGER === 9007199254740991
// true
Number.MIN_SAFE_INTEGER === -Number.MAX_SAFE_INTEGER
// true
Number.MIN_SAFE_INTEGER === -9007199254740991
// true
Number.isSafeInteger()则是用来判断一个整数是否落在安全范围之内。
Number.isSafeInteger('a') // false
Number.isSafeInteger(null) // false
Number.isSafeInteger(NaN) // false
Number.isSafeInteger(Infinity) // false
Number.isSafeInteger(-Infinity) // false
Number.isSafeInteger(3) // true
Number.isSafeInteger(1.2) // false
Number.isSafeInteger(9007199254740990) // true
Number.isSafeInteger(9007199254740992) // false
Number.isSafeInteger(Number.MIN_SAFE_INTEGER - 1) // false
Number.isSafeInteger(Number.MIN_SAFE_INTEGER) // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER) // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1) // false
实际使用这个函数时,需要注意。验证运算结果是否落在安全整数的范围内,不要只验证运算结果,而要同时验证参与运算的每个值。
在计算中,如果参与计算的某一个值超出了精度范围,计算机内部,会以9007199254740992的形式储存,即以9007199254740992参与实际计算。
Number.isSafeInteger(9007199254740993)
// false
Number.isSafeInteger(990)
// true
Number.isSafeInteger(9007199254740993 - 990)
// true
9007199254740993 - 990
// 返回结果 9007199254740002 = 9007199254740992-990
// 正确答案应该是 9007199254740003 = 9007199254740993 - 990
Number.isInteger()用来判断一个数值是否为整数。同时,如果参数不是数值,Number.isInteger返回false
Number.isInteger(25) // true
Number.isInteger(25.0) // true
Number.isInteger(25.1) // false
// 参数不是数值
Number.isInteger() // false
Number.isInteger(null) // false
Number.isInteger('15') // false
Number.isInteger(true) // false
// 小数的精度达到了小数点后16个十进制位,转成二进制位超过了53个二进制位,导致最后的那个2被丢弃了
Number.isInteger(3.0000000000000002) // true
Number.isInteger(5E-324) // false
// 5E-325小于最小值5E-324,会被自动转为0,因此返回true
Number.isInteger(5E-325) // true
注意
- JavaScript 内部,整数和浮点数采用的是同样的储存方法,所以 25 和 25.0 被视为同一个值。
- 同样受精度影响,超过安全范围的值可能会判断误判。
Number对象没有判断是否为浮点数的方法,因为非数值Number.isInteger也会被判断为false,所以并不能单纯用取反Number.isInteger来判断是否为浮点数
const a = 0.01
const b = '0.01'
Number.isInteger(a) // true
Number.isInteger(b) // true
// 联合Number.isFinite方法一起判断
Number.isFinite(a) && !Number.isInteger(a) // true
Number.isFinite(b) && !Number.isInteger(b) // false
2.3 Number.parseInt(), Number.parseFloat()
ES6 将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。
这样做的目的,是逐步减少全局性方法,使得语言逐步模块化。
// ES5的写法
parseInt('12.34') // 12
parseFloat('123.45#') // 123.45
// ES6的写法
Number.parseInt('12.34') // 12
Number.parseFloat('123.45#') // 123.45
3. 数值分隔符
欧美语言中,较长的数值允许每三位添加一个分隔符(通常是一个逗号),增加数值的可读性。比如,1000可以写作1,000。
ES2021,允许 JavaScript 的数值使用下划线(_)作为分隔符。这个数值分隔符没有指定间隔的位数,也就是说,可以每三位添加一个分隔符,也可以每一位、每两位、每四位添加一个。而且整数和小数,包括科学计数法都可以添加
// 整数
123_00 === 12_300 // true
12345_00 === 123_4500 // true
12345_00 === 1_234_500 // true
// 小数
0.000_001
// 科学计数法
1e10_000
// 二进制
0b1010_0001_1000_0101
// 八进制
0o76_543_21_0
// 十六进制
0xA0_B0_C0
数值分隔符有几个使用注意点。
- 不能放在数值的最前面(leading)或最后面(trailing)。
- 不能两个或两个以上的分隔符连在一起。
- 小数点的前后不能有分隔符。
- 科学计数法里面,表示指数的e或E前后不能有分隔符。
- 分隔符不能紧跟着进制的前缀
0b、0B、0o、0O、0x、0X
数值分隔符只是一种书写便利,对于 JavaScript 内部数值的存储和输出,并没有影响。同时数值分隔符也只有数值类型支持,如果换成字符串则会被当做普通字符串处理。主要原因是语言的设计者认为,数值分隔符主要是为了编码时书写数值的方便,而不是为了处理外部输入的数据。
Number('123_456') // NaN
Number(123_456) // 123456
parseInt('123_456.01') // 123
parseInt(123_456.01) // 123456
parseFloat('0.000_100') // 0
parseFloat(0.000_100) // 0.0001
本文介绍了ES6中数值的扩展,包括二进制、八进制和十六进制的表示方法及其转换,详细讲解了Number对象的isFinite()、isNaN()、isInteger()、isSafeInteger()等方法,以及数值分隔符的使用规范。这些更新提高了JavaScript中处理数值的便利性和可读性。
1337

被折叠的 条评论
为什么被折叠?



