ECMAScript 6之数值的扩展
目录
1. 二进制和八进制的表示
ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b
(或0B
)和0o
(或0O
)表示。
// 数值转为二进制字符
(369).toString(2); // "101110001"
// 数值转为八进制字符
369..toString(8); // "561"
// 二进制用0b或oB表示
0b101110001 === 369; // true
0B101110001 === 369; // true
// 八进制用0o或0O表示
0o561 === 369; // true
0O561 === 369; // true
上面代码中,数值369
没有直接调用toString()
方法,如果不加括号直接调用toString()
,这个点会被 JavaScript 引擎解释成小数点,从而报错。有以下方法可以避免这个问题。
- 数值加上括号(
()
) - 在数值后面加两个点,JavaScript 会把第一个点理解成小数点,把第二个点理解成调用对象属性,从而得到正确结果
- 通过方括号运算符(
[]
)调用
// 数值加()调用
(234).toString(2); // "11101010"
// 数值加.调用
234..toString(2); // "11101010"
// 通过[]调用
234['toString'](2); // "11101010"
2. Number.isFinite(), Number.isNaN()
ES6 在Number
对象上,提供了Number.isFinite()
和Number.isNaN()
两个方法。Number.isFinite()
用来检查一个数值是否为有限的;Number.isNaN()
用来检查一个数值是否为NaN
。
// Number.isFinite()检查一个数是否是有限的
Number.isFinite(15); // true
Number.isFinite(0.8); // true
// 参数类型不是数值,一律返回false
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite('jidi'); // false
Number.isFinite('1'); // false
Number.isFinite(true); // false
// Number.isNaN()检查一个数是否为NaN
Number.isNaN(NaN) // true
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true
// 参数类型不是NaN,一律返回false
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
注意:
·Number.isFinite()
的参数类型如果不是数值,一律返回false
;Number.isNan()
的参数如果不是NaN
,一律返回true
。
2.1 Number.isFinite(),Number.isNaN()与全局方法isFinite(),isNaN()的区别
全局方法isFinite()
和isNaN()
会先调用Number()
方法将非数值类型的参数转换为数据类型的值,然后再进行判断,而Number.isFinite()
与Number.isNaN()
两个方法只对数值有效。Number.isFinite()
的参数如果不是数值类型,一律返回false
。Number.isNaN()
的参数非NaN
一律返回true
。
// isFinite()会先调用Number方法进行数据类型转换,然后进行判断
isFinite(25); // true
isFinite("25"); // true
// Number.isFinite()只对数值有效
Number.isFinite(25); // true
Number.isFinite("25"); // false
// isNaN()会先调用Number方法进行数据类型转换,然后进行判断
isNaN(NaN) // true
isNaN("NaN") // true
// Number.isNaN()只对数值有效
Number.isNaN(NaN) // true
Number.isNaN("NaN") // false
Number.isNaN(1) // false
3. Number.parseInt(),Number.parseFloat()
ES6 将全局方法parseInt()
和parseFloat()
,移植到了Number
对象上面,行为完全保持不变。
// ES5写法
parseInt('123'); // 123
parseInt(' 81'); // 81
parseInt(1.23); // 1
parseInt('8a'); // 8
parseInt('12**'); // 12
parseInt('12.34'); // 12
parseInt('15e2'); // 15
parseInt('15px'); // 15
parseInt('abc'); // NaN
parseInt('.3'); // NaN
parseInt(''); // NaN
parseInt('+'); // NaN
parseInt('1000', 2); // 8
parseInt('1000', 6); // 216
parseInt('1000', 8); // 512
// ES6写法
Number.parseInt('123'); // 123
Number.parseInt(' 81'); // 81
Number.parseInt(1.23); // 1
Number.parseInt('8a'); // 8
Number.parseInt('12**'); // 12
Number.parseInt('12.34'); // 12
Number.parseInt('15e2'); // 15
Number.parseInt('15px'); // 15
Number.parseInt('abc'); // NaN
Number.parseInt('.3'); // NaN
Number.parseInt(''); // NaN
Number.parseInt('+'); // NaN
Number.parseInt('1000', 2); // 8
Number.parseInt('1000', 6); // 216
Number.parseInt('1000', 8); // 512
4. Number.isInteger()
Number.isInteger()
用来判断一个数值是否为整数。
Number.isInteger(5); // true
Number.isInteger(5.0); // true
Number.isInteger(5.6); // false
上面代码中,5
和5.0
结果一样,因为javaScript内部,整数和浮点数用的同一种存储方法(参考JavaScript教程)。
根据国际标准 IEEE 754,JavaScript 提供的有效数字最长为53个二进制位。当数值的精度超过这个标准,Number.isInteger()
会失真。
// 超过精度范围,判断失真
Number.isInteger(1.000000000000000000000000000000000000002); // true
5. Number.EPSILON
ES6 新增一个极小的常量Number.EPSILON
,它表示 1
与大于1
的最小浮点数之间的差。由于数字在javaScript内部使用64位浮点数存储,所以Number.EPSILON
相当于2
的-52
次方。
Number.EPSILON === Math.pow(2, -52); // true
Number.EPSILON; // 2.220446049250313e-16
由于浮点数的计算是不精确的,Number.EPSILON
的实质是一个可以接受的最小误差范围。
// 浮点数的计算是不精确的
0.1 + 0.7; // 0.7999999999999999
// 在最小误差范围内,可以认为两个数相等
2 + Number.EPSILON === 2;
6. 安全整数和 Number.isSafeInteger()
JavaScript 能够准确表示的整数范围在-253
和253
之间(开区间),超过这个范围,无法精确表示这个值。
ES6 引入了Number.MAX_SAFE_INTEGER
和Number.MIN_SAFE_INTEGER
这两个常量,用来表示这个范围的上下限。Number.isSafeInteger()
则是用来判断一个整数是否落在这个范围之内.。
Math.pow(2, 53) - 1; // 9007199254740991
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
// 判断一个数是否在-9007199254740991~9007199254740991之间
Number.isSafeInteger('jidi'); // 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
注意:
使用Number.isSafeInteger()
函数进行验证时,不要只验证运算结果,而要同时验证参与运算的每个值。
7. 指数运算符
ES2016 新增了一个指数运算符(**
)。**
是右结合的,多个指数运算可以连用。
2 ** 2; // 4
2 ** 3; // 8
// 多个指数运算符连用
2 ** 3 ** 2; // 512
8. BigInt 数据类型
由于JavaScript 所有数字都用64 位浮点数进行存储,数值的精度只能到 53
个二进制位,而且大于或等于2
的1024
次方的数值(小于或等于-2
的1023
次方的数值),JavaScript 无法表示,会返回Infinity
(-Infinity
)。
// 超过 53 个二进制位的数值,无法保持精度
Math.pow(2, 53) === Math.pow(2, 53) + 1; // true
// 超过 2 的 1024 次方的数值,无法表示
Math.pow(2, 1025); // Infinity
ES2020 引入了一种新的数据类型 BigInt
,来解决这个问题。BigInt
只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示。BigInt
类型的数据必须添加后缀n
。
// Bigint数据后面加后缀n
const a = 21721416122353n;
const b = 153463491231309n;
// BigInt精度可以保证
a*b; // 3333444352624333556168350077n
Bigint
类型的数据与普通数值是两种值,并不相等。
const c1 = 12n;
const c2 = 12;
typeof c1; // "bigint"
typeof c2; // "number"
// 两者不相等
c1 === c2; // false
8.1 BigInt 对象
JavaScript 原生提供BigInt
对象,可以用作构造函数生成 BigInt 类型的数值。BigInt()
构造函数必须有参数,而且参数必须可以正常转为数值。
// 用法参照Number()
BigInt(123) // 123n
BigInt('123') // 123n
BigInt(false) // 0n
BigInt(true) // 1n
// Bigint()必须有参数,且参数必须能转为数值
new BigInt(); // Uncaught TypeError: BigInt is not a constructor at new BigInt
BigInt(undefined); // Uncaught TypeError: Cannot convert undefined to a BigInt
BigInt(null); // Uncaught TypeError: Cannot convert null to a BigInt at BigInt
BigInt(NaN); // Uncaught RangeError: The number NaN cannot be converted to a BigInt because it is not an integer
BigInt(Infinity); // Uncaught RangeError: The number Infinity cannot be converted to a BigInt because it is not an integer at BigInt
BigInt()
构造函数参数不能为小数。
BigInt(1.1); // Uncaught RangeError: The number 1.1 cannot be converted to a BigInt because it is not an integer at BigInt
BigInt 类型的+
、-
、*
和**
这四个二元运算符,与 Number 类型的行为一致。除法运算/
会舍去小数部分,返回一个整数。
12n + 12n; // 24n
2n * 2n; // 4n
12n - 2n; // 10n
2n ** 3n; // 8n
// 除法会舍去小数部分,返回整数
10n / 6n; // 1n
BigInt 不能与普通数值进行混合运算。
1n + 32; // Uncaught TypeError: Cannot mix BigInt and other types
有两个数值运算符不能用在Bigint数据类型的值上。
- 无符号右移
>>>
- 一元求正
+
>>>
是无符号右移,而Bigint数据类型的总是带符号的,所以该运算无意义;而一元+
运算符结果是返回Number的,会报错。
+ 12n; // Uncaught TypeError: Cannot convert a BigInt value to a number
跟一元求正运算符一样,如果一个标准库函数的参数预期是Number
类型,但是得到的是一个 BigInt
,就会报错。
Math.pow(2n, 2); // Uncaught TypeError: Cannot convert a BigInt value to a number at Math.pow
Math.abs(4n); // Uncaught TypeError: Cannot convert a BigInt value to a number at Math.abs
9. 参考链接
本篇博文是我自己学习笔记,原文请参考:ECMAScript 6 入门
如有问题,请及时指出!
欢迎沟通交流,邮箱:jidi_jidi@163.com。