ES6+ 数值扩展

1. 前言

ES6 对数值进行了大的改版,在向下兼容的同时,把所有的数值方法由全局移植到了 Number 对象下,在数组和字符串中也做了类似的操作,这样的主要目的是精简全局方法,更加明确的表达方法的含义。另外,ES6 还增加了二进制和八进制的表示方法,并增加了很多数值处理的方法,本节就来看看 ES6 对数值的扩展。

2. Number 对象

JavaScript 的 Number 对象是经过封装的,能让你处理数字值的对象, Number 对象由 Number() 构造器创建。

2.1 类型转换

在非构造器上下文中,也就是没有 new 操作符时,Number 可以类型转换的函数使用。 接收一个参数,并将这个参数转换为数字,如果参数无法被转换为数字,则返回 NaN

Number('10')			 	// 10
Number('imooc')		 	// NaN
Number('')					// 0
Number()						// 0
Number(undefined)		// NaN

上面的代码中,在没有字符串或者是空字符串的时候,会得到数字 0,还有参数是 null 时得到的结果也是 0。但是,当参数为 undefined 时则会得到 NaN

2.2 移植全局方法

在 ES5 中,如 parseFloatparseInt 等都是全局方法,在 ES6 中把处理数值的一些方法都移植到了 Number 对象上了。

parseInt('123');				// 123
Number.parseInt('123');	// 123

上面的代码可以看到,Number 对象下也有 parseInt 的方法,并且所有的数值方法在 Number 上也是一一对应的,功能基本相同,有些方法还做了扩展。在后面的小节中我们会对 Number 上的方法和全局的方法进行对比,看它们有什么不同,ES6 又解决了什么问题。

3. 二进制和八进制表示法

ES6 提供了二进制和八进制数值表示的新写法,分别用前缀 0b(或 0B)和 0o(或 0O)表示。对应的十六进制我们知道用 0x 作为前缀来表示的。下面我们来看看二进制和八进制是怎么表示的。

// es6 2进制 0B 开头
console.log('B',0B111110111); 	// 503
console.log('B',0b111110111); 	// 相同,0B 和 0b 都可以

// es6 8进制 0o 开头
console.log(0o767); 	// 503
console.log(0O767); 	// 相同,0o 和 0O 都可以

上面的代码分别使用了二进制和八进制对数字 503 进行了表示,那下面我们来验证一下:

0b111110111 === 503 // true
0o767 === 503 		// true

上面的代码中使用了全等的方式进行判断,很明显,ES6 是支持这种方式的表示的。

从 ES5 开始,在严格模式之中,八进制就不再允许使用前缀 0 表示,ES6 进一步明确,要使用前缀 0o 表示。

// 非严格模式
(function(){
  console.log(0o11 === 011);	// true
})()

// 严格模式
(function(){
  'use strict';
  console.log(0o11 === 011);
})()
// Uncaught SyntaxError: Octal literals are not allowed in strict mode.

0b0o 前缀的字符串数值转为十进制,可以把 Number 对象直接作为方法使用。

Number('0b111')  // 7
Number('0o10')   // 8

4. Number 的属性介绍

ES6 对 Number 的属性进行了丰富,能够适用更多的场景。

4.1 Number.EPSILON

ES6 在 Number 对象上面,新增一个极小的常量 Number.EPSILON。它表示 1 与大于 1 的最小浮点数之间的差。它是一个差值,属于正数。

你不必创建一个 Number 对象来访问这个静态属性(可以直接使用 Number.EPSILON)。

console.log(Number.EPSILON) // 2.220446049250313e-16

EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16,或者 2 的 -52 次方。

对于 64 位浮点数来说,大于 1 的最小浮点数相当于二进制的 1.00…001,小数点后面有连续 51 个零。这个值减去 1 之后,就等于 2 的 -52 次方。

0.1 + 0.2
// 0.30000000000000004

0.1 + 0.2 - 0.3
// 5.551115123125783e-17

5.551115123125783e-17.toFixed(20)
// '0.00000000000000005551'
上面代码解释了,为什么比较0.1 + 0.20.3得到的结果是false0.1 + 0.2 === 0.3 // false

Number.EPSILON 实际上是 JavaScript 能够表示的最小精度。误差如果小于这个值,就可以认为已经没有意义了,即不存在误差了。

引入一个这么小的量的目的,在于为浮点数计算,设置一个误差范围。我们知道浮点数计算是不精确的。

5.551115123125783e-17 < Number.EPSILON * Math.pow(2, 2)
// true

4.2 Number.MAX_SAFE_INTEGER

Number.MAX_SAFE_INTEGER 常量表示在 JavaScript 中最大的安全整数(maxinum safe integer)(2e53 - 1)。

console.log(Number.MAX_SAFE_INTEGER) 	// 9007199254740991

MAX_SAFE_INTEGER 是一个值为 9007199254740991 的常量。因为 Javascript 的数字存储使用了 IEEE-754 中规定的双精度浮点数数据类型,而这一数据类型能够安全存储 -(2e53 - 1)2e53 - 1 之间的数值(包含边界值)。

由于 MAX_SAFE_INTEGER 是 Number 的一个静态属性,所以你不用自己动手为 Number 对象创建 Number.MAX_SAFE_INTEGER 这一属性,就可以直接使用它。

4.3 Number.MIN_SAFE_INTEGER

Number.MIN_SAFE_INTEGER 代表在 JavaScript 中最小的安全的 integer 型数字 (-(253 - 1))。

console.log(Number.MIN_SAFE_INTEGER) 	// -9007199254740991

MIN_SAFE_INTEGER 的值是 -9007199254740991. 形成这个数字的原因是 JavaScript 在 IEEE-754 中规定的。在这个规定中能安全地表示数字的范围在 -(2e53 - 1)2e53 - 1之间

由于 MIN_SAFE_INTEGER 是 Number 的一个静态属性,你可以直接使用 Number.MIN_SAFE_INTEGER, 而不是自己去创建一个 Number 的属性。

5. 小结

本节主要讲解了 ES6 对数值的扩展主要总结一下几点:

  • 增加了二进制和八进制表示法;
  • 直接使用 Number 进行类型转换;
  • 移植了原有的方法到 Number 对象上;
  • 对新增的 Number 对象上的属性做了简单的解释。

ES6 的 Number 对象还提供了很多方法,下面的小节会讲到,还有 ES6 对数字的处理在 Math 小节做详细的讲解。