ES6之数值的扩展

date
Jun 13, 2018
slug
swmwlohc
status
Published
tags
JavaScript
summary
type
Post
 
[TOC]
ES6 中二进制前缀:0b(或 0B),八进制前缀:0o(或 0O)。使用 Number 方法将字符串数值转为十进制
Number('0b111')  // 7Number('0o10')  // 8
isFinite()、isNaN():传统的全局方法 isFinite()和 isNaN()的是先调用 Number()将非数值的值转为数值,再进行判断,而这两个新方法只对数值有效,Number.isFinite()对于非数值一律返回 false, Number.isNaN()只有对于 NaN 才返回 true,非 NaN 一律返回 false。
Number.isFinite(0.8); // trueNumber.isFinite(NaN); // falseNumber.isFinite(Infinity); // falseNumber.isFinite(-Infinity); // falseNumber.isFinite('foo'); // falseNumber.isFinite('15'); // falseNumber.isFinite(true); // false
parseInt()、parseFloat():ES6 将全局方法 parseInt()和 parseFloat(),移植到 Number 对象上面,行为完全保持不变。目的是逐步减少全局性方法,使得语言逐步模块化。
isInteger():对数据精度的要求较高时,判断一个数值是否为整数,不是数值返回 false。JavaScript 内部,整数和浮点数采用的是同样的储存方法,所以 25 和 25.0 被视为同一个值。
Number.EPSILON:极小的常量,它表示 1 与大于 1 的最小浮点数之间的差,等于 2 的 -52 次方。可以用来设置“能够接受的误差范围”,即如果两个浮点数的差小于这个值,我们就认为这两个浮点数相等,或单独设定误差范围。
0.1 + 0.2// 0.300000000000000040.1 + 0.2 - 0.3// 5.551115123125783e-170.1 + 0.2 - 0.3 < Number.EPSILON// true// 误差范围设为 2 的-50 次方function withinErrorMargin (left, right) {  return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);}0.1 + 0.2 === 0.3 // falsewithinErrorMargin(0.1 + 0.2, 0.3) // true1.1 + 1.3 === 2.4 // falsewithinErrorMargin(1.1 + 1.3, 2.4) // true
isSafeInteger:MAX_SAFE_INTEGER、MIN_SAFE_INTEGER 分表表示整数范围在-2^53 到 2^53 之间。实际使用这个函数时,需要注意。验证运算结果是否落在安全整数的范围内,不要只验证运算结果,而要同时验证参与运算的每个值。

Math 对象的扩展

Math.trunc():用于去除一个数的小数部分,返回整数部分。对于非数值,Math.trunc 内部使用 Number 方法将其先转为数值。对于空值和无法截取整数的值,返回 NaN。
Math.trunc(4.9) // 4Math.trunc(-4.1) // -4Math.trunc('123.456') // 123Math.trunc(true) //1Math.trunc(false) // 0Math.trunc(null) // 0Math.trunc(NaN);      // NaNMath.trunc('foo');    // NaNMath.trunc();         // NaNMath.trunc(undefined) // NaN
Math.sign:判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值,对于那些无法转为数值的值,会返回 NaN。参数为正数,返回+1;参数为负数,返回-1;参数为 0,返回 0;参数为-0,返回-0;其他值,返回 NaN。
Math.cbrt:计算一个数的立方根。对于非数值,会先将其转换为数值。
Math.clz32:将参数转为 32 位无符号整数的形式,然后返回这个 32 位值里面有多少个前导 0。对于非数值,会先将其转换为数值。对于小数,Math.clz32 方法只考虑整数部分。左移运算符(<<)与 Math.clz32 方法直接相关。
Math.imul:返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。
Math.fround:返回一个数的 32 位单精度浮点数形式。
Math.hypot:返回所有参数的平方和的平方根。

对数

Math.expm1、Math.log1p、Math.log10、Math.log2

双曲函数

  • Math.sinh(x) 返回 x 的双曲正弦(hyperbolic sine)
  • Math.cosh(x) 返回 x 的双曲余弦(hyperbolic cosine)
  • Math.tanh(x) 返回 x 的双曲正切(hyperbolic tangent)
  • Math.asinh(x) 返回 x 的反双曲正弦(inverse hyperbolic sine)
  • Math.acosh(x) 返回 x 的反双曲余弦(inverse hyperbolic cosine)
  • Math.atanh(x) 返回 x 的反双曲正切(inverse hyperbolic tangent)

指数运算符

多个指数运算符连用时,是从最右边开始计算的。注意,V8 引擎的指数运算符与 Math.pow 的实现不相同,对于特别大的运算结果,两者会有细微的差异。
2 ** 2 // 42 ** 3 // 82 ** 3 ** 2 // 512,相当于 2 ** (3 ** 2)a **= 2; // 等同于 a = a * a;b **= 3;// 等同于 b = b * b * b;Math.pow(99, 99)// 3.697296376497263e+19799 ** 99// 3.697296376497268e+197

BigInt

JavaScript 所有数字都保存成 64 位浮点数 ,这给数值的表示带来了两大限制:
  • 一是数值的精度只能到 53 个二进制位(相当于 16 个十进制位),大于这个范围的整数,JavaScript 是无法精确表示的,这使得 JavaScript 不适合进行科学和金融方面的精确计算。
  • 二是大于或等于 2 的 1024 次方的数值,JavaScript 无法表示,会返回 Infinity。
ES2020 引入了一种新的数据类型 BigInt(大整数),只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示。BigInt 同样可以使用各种进制表示,都要加上后缀 n。
1234 // 普通整数1234n // BigInt// BigInt 的运算1n + 2n // 3n0b1101n // 二进制0o777n // 八进制0xFFn // 十六进制42n === 42 // false,但是宽松相等的typeof 123n // 'bigint'// 可以使用负号(-),但是不能使用正号(+),因为会与 asm.js 冲突。-42n // 正确+42n // 报错

BigInt 对象

JavaScript 原生提供 BigInt 对象,可以用作构造函数生成 BigInt 类型的数值。转换规则基本与 Number()一致,将其他类型的值转为 BigInt。
BigInt(123) // 123nBigInt('123') // 123nBigInt(false) // 0nBigInt(true) // 1n
BigInt()构造函数必须有参数,而且参数必须可以正常转为数值,下面的用法都会报错。
new BigInt() // TypeErrorBigInt(undefined) //TypeErrorBigInt(null) // TypeErrorBigInt('123n') // SyntaxError   // 123n无法解析成 Number 类型,所以会报错。BigInt('abc') // SyntaxErrorBigInt(1.5) // RangeErrorBigInt('1.5') // SyntaxError
  • BigInt.prototype.toString():继承了 Object 对象
  • BigInt.prototype.valueOf():继承了 Object 对象
  • BigInt.prototype.toLocaleString():继承了 Number 对象
  • BigInt.asUintN(width, BigInt):静态方法,给定的 BigInt 转为 0 到 2width - 1 之间对应的值。
  • BigInt.asIntN(width, BigInt):静态方法,给定的 BigInt 转为 -2width - 1 到 2width - 1 - 1 之间对应的值。
  • BigInt.parseInt(string[, radix]):静态方法,近似于 Number.parseInt(),将一个字符串转换成指定进制的 BigInt。
对于二进制数组,BigInt 新增了两个类型 BigUint64Array 和 BigInt64Array,这两种数据类型返回的都是 64 位 BigInt。DataView 对象的实例方法 DataView.prototype.getBigInt64()和 DataView.prototype.getBigUint64(),返回的也是 BigInt。

转换规则

Boolean(0n) // falseBoolean(1n) // trueNumber(1n)  // 1String(1n)  // "1"!0n // true!1n // false

数学运算

BigInt 类型的+、-、*和**这四个二元运算符,与 Number 类型的行为一致。除法运算/会舍去小数部分,返回一个整数。几乎所有的数值运算符都可以用在 BigInt,但是有两个例外。
  • 不带符号的右移位运算符>>>:>>>运算符是不带符号的,但是 BigInt 总是带有符号的,导致该运算无意义,完全等同于右移运算符>>。
  • 一元的求正运算符+:在 asm.js 里面总是返回 Number 类型,为了不破坏 asm.js 就规定+1n 会报错。
9n / 5n // 1n// Math.sqrt的参数预期是 Number 类型Math.sqrt(4n) // 报错Math.sqrt(Number(4n)) // 2
  • 不能与普通数值进行混合运算,无论返回的是 BigInt 或 Number,都会导致丢失精度信息。
  • 比较运算符(比如>)和相等运算符(==)允许 BigInt 与其他类型的值混合计算,因为这样做不会损失精度。
  • BigInt 与字符串混合运算时,会先转为字符串,再进行运算。
1n + 1.3 // 报错1n | 0 // 报错if (0n) {  console.log('if');}0n < 1 // true0n < true // true0n == 0 // true0n == false // true0n === 0 // false'' + 123n // "123"

© 刘德华 2020 - 2023