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 不同进制转换

  1. 使用Number方法可以将不同进制的数值转为十进制的数值
Number(0x10) // 16
Number(0O10) // 8
Number(0b10) // 2
  1. 使用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()将非数值的值转换为数值,再进行判断,而这两个新方法只对数值有效。

  1. 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
  1. Number.isNaN()用来检查一个值是否为NaN。同时,如果参数类型不是NaNNumber.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^532^53之间(不含两个端点),如果数值的精度超过这个限度,第54位及后面的位就会被丢弃。

Math.pow(2, 53) // 9007199254740992

9007199254740992  // 9007199254740992
9007199254740993  // 9007199254740992 (精度丢失)

Math.pow(2, 53) === Math.pow(2, 53) + 1
// true
  1. ES6 引入了Number.MAX_SAFE_INTEGERNumber.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
  1. 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
  1. 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前后不能有分隔符。
  • 分隔符不能紧跟着进制的前缀0b0B0o0O0x0X

数值分隔符只是一种书写便利,对于 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

猜你喜欢

转载自blog.csdn.net/BAtodl/article/details/121407791