ES6里关于数字的拓展
一、指数运算符
ES6引入的唯一一个JS语法变化是求幂运算符,它是一种将指数应用于基数的数学运算。JS已有的Math.pow()方法可以执行求幂运算,但它也是为数不多的需要通过方法而不是正式的运算符来进行求幂
求幂运算符是两个星号(**):左操作数是基数,右操作数是指数
let result = 5 ** 2;
console.log(result) //
console.log(result === Math.pow(,) ) // true
指数运算符可以与等号结合,形成一个新的赋值运算符(**=
)
let c=;
c**=
//等价于c=c*c*c
注意:在 V8 引擎中,指数运算符与Math.pow
的实现不相同,对于特别大的运算结果,两者会有细微的差异
1、运算顺序:
求幂运算符具有JS中所有二进制运算符的优先级(一元运算符的优先级高于**),这意味着它首先应用于所有复合操作
let result = * **
console.log(result) // 50
//先计算52,然后将得到的值乘以2,最终结果为50
2、运算限制:
求幂运算符确实有其他运算符没有的一些不寻常的限制,它左侧的一元表达式只能使用++或--
//语法错误
let result =- **
此示例中的-5的写法是一个语法错误,因为运算的顺序是不明确的。-是只适用于5呢,还是适用于表达式5**2的结果?禁用求幂运算符左侧的二元表达式可以消除歧义。要明确指明意图,需要用括号包裹-5或5**2
//可以包裹5**2
let result1 =-( ** ) //-25 //也可以包裹-5
let result2 = (-) ** // 等于25
如果在表达式两端放置括号,则-将应用于整个表达式;如果在-5两端放置括号,则表明想计算-5的二次幕。
在求幕运算符左侧无须用括号就可以使用++和--,因为这两个运算符都明确定义了作用于操作数的行为。前缀++或--会在其他所有操作发生之前更改操作数,而后缀版本直到整个表达式被计算过后才会进行改变。这两个用法在运算付左侧都是安全的
let num1 = ,
num2 = ;
console.log(++num1 ** ) //
console.log(num1) //
console.log(num2--** ) //
console.log(num2) // 1
//在这个示例中,num1在应用取幂运算符之前先加1,所以num1变为3,运算结果为9;而num2取幂运算的值保持为2,之后再减1
最佳方式是:把优先级按括号括起来
二、不同进制
ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b
(或0B
)和0o
(或0O
)表示
0b111110111 === // true
0o767 === // true
从 ES5 开始,在严格模式之中,八进制就不再允许使用前缀0
表示,ES6 进一步明确,要使用前缀0o
表示
如果要将0b
和0o
前缀的字符串数值转为十进制,要使用Number
方法
Number('0b111') //
Number('0o10') //
三、Number方法
ES6 在Number
对象上,新提供了Number.isFinite()
和Number.isNaN()
两个方法
1、Number.isFinite():
Number.isFinite()
用来检查一个数值是否为有限的(finite)。
与原有的isFinite()方法的不同之处在于,Number.isFinite()方法没有隐式的Number()类型转换,对于非数值一律返回false。
//ES5 可以通过下面的代码,部署Number.isFinite方法 (function (global) {
var global_isFinite = global.isFinite; Object.defineProperty(Number, 'isFinite', {
value: function isFinite(value) {
return typeof value === 'number' && global_isFinite(value);
},
configurable: true,
enumerable: false,
writable: true
});
})(this);
2、Number.isNaN()
Number.isNaN()
用来检查一个值是否为NaN。
与原有的isNaN()方法不同,不存在隐式的Number()类型转换,非
NaN
一律返回false。
3、ES6 将全局方法parseInt()
和parseFloat()
,移植到Number
对象上面,行为完全保持不变。
// ES5的写法
parseInt('12.34') //
parseFloat('123.45#') // 123.45 // ES6的写法
Number.parseInt('12.34') //
Number.parseFloat('123.45#') // 123.45
这样做的目的,是逐步减少全局性方法,使得语言逐步模块化
Number.parseInt === parseInt // true
Number.parseFloat === parseFloat // true
4、Number.isInteger()
Number.isInteger()
用来判断一个值是否为整数。需要注意的是,在JS内部,整数和浮点数是同样的储存方法,所以3和3.0被视为同一个值
Number.isInteger() // true
Number.isInteger(25.0) // true
Number.isInteger(25.1) // false
Number.isInteger("") // false
Number.isInteger(true) // false
//ES5 可以通过下面的代码,部署Number.isInteger() (function (global) {
var floor = Math.floor,
isFinite = global.isFinite; Object.defineProperty(Number, 'isInteger', {
value: function isInteger(value) {
return typeof value === 'number' &&
isFinite(value) &&
floor(value) === value;
},
configurable: true,
enumerable: false,
writable: true
});
})(this);
四、Number常量
1、Number.EPSILON
ES6在Number对象上面,新增一个极小的常量Number.EPSILON
Number.EPSILON// 2.220446049250313e-16
Number.EPSILON.toFixed()// '0.00000000000000022204'
引入一个这么小的量的目的,在于为浮点数计算,设置一个误差范围
0.1 + 0.2// 0.30000000000000004 0.1 + 0.2 - 0.3// 5.551115123125783e-17 5.551115123125783e-17.toFixed()// '0.00000000000000005551'
但是如果这个误差能够小于Number.EPSILON
,我们就可以认为得到了正确结果,因此,Number.EPSILON
的实质是一个可以接受的误差范围。
function withinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON;
}
withinErrorMargin(0.1 + 0.2, 0.3)// true
withinErrorMargin(0.2 + 0.2, 0.3)// false
//此代码为浮点数运算,部署了一个误差检查函数
2、安全整数
JS能够准确表示的整数范围在-2^53
到2^53
之间(不含两个端点),超过这个范围,无法精确表示这个值
3、Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER
ES6引入了Number.MAX_SAFE_INTEGER
和Number.MIN_SAFE_INTEGER
这两个常量,用来表示这个范围的上下限
Number.MAX_SAFE_INTEGER === Math.pow(, ) - // true
Number.MAX_SAFE_INTEGER === // true Number.MIN_SAFE_INTEGER === -Number.MAX_SAFE_INTEGER // true
Number.MIN_SAFE_INTEGER === - // true
4、Number.isSafeInteger()
Number.isSafeInteger()
则是用来判断一个整数是否落在这个范围之内,浮点数是为false的
//这个函数的实现很简单,就是跟安全整数的两个边界值比较一下
Number.isSafeInteger = function (n) {
return (typeof n === 'number' &&
Math.round(n) === n &&
Number.MIN_SAFE_INTEGER <= n &&
n <= Number.MAX_SAFE_INTEGER);
}
实际使用这个函数时,需要注意验证运算结果是否落在安全整数的范围内,不要只验证运算结果,而要同时验证参与运算的每个值
Number.isSafeInteger() // false
Number.isSafeInteger() // true
Number.isSafeInteger( - ) // true -
// 返回结果 9007199254740002
// 正确答案应该是 9007199254740003
上面代码中,9007199254740993
不是一个安全整数,但是Number.isSafeInteger
会返回结果,显示计算结果是安全的。这是因为,这个数超出了精度范围,导致在计算机内部,以9007199254740992
的形式储存
=== // true
五、Math对象
ES6在Math对象上新增了17个与数学相关的方法。所有这些方法都是静态方法,只能在Math对象上调用
1、Math.trunc
Math.trunc
方法用于去除一个数的小数部分,返回整数部分
Math.trunc(4.9) //
Math.trunc(-4.1) // -4
Math.trunc(-0.1234) // -0 //对于非数值,Math.trunc内部使用Number方法将其先转为数值
Math.trunc('123.456')// 123 //对于空值和无法截取整数的值,返回NaN
Math.trunc(NaN); // NaN
Math.trunc('foo'); // NaN
Math.trunc(); // NaN
对于没有部署这个方法的环境,可以用下面的代码模拟
Math.trunc = Math.trunc || function(x) {
return x < ? Math.ceil(x) : Math.floor(x);
};
2、Math.sign
Math.sign
方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。它会返回以下五种值:
(1)参数为正数,返回+1;(2)参数为负数,返回-1;(3)参数为0,返回0;(4)参数为-0,返回-0;(5)其他值,返回NaN。
对于没有部署这个方法的环境,可以用下面的代码模拟
Math.sign = Math.sign || function(x) {
x = +x; // convert to a number
if (x === || isNaN(x)) {
return x;
}
return x > ? : -;
};
3、Math.cbrt
Math.cbrt
方法用于计算一个数的立方根。对于非数值,Math.cbrt
方法内部也是先使用Number
方法将其转为数值。
//对于没有部署这个方法的环境,可以用下面的代码模拟
Math.cbrt = Math.cbrt || function(x) {
var y = Math.pow(Math.abs(x), /);
return x < ? -y : y;
};
4、Math.clz32
JS的整数使用32位二进制形式表示,Math.clz32
方法返回一个数的32位无符号整数形式有多少个前导0
Math.clz32() //
Math.clz32() //
Math.clz32() //
Math.clz32(0b01000000000000000000000000000000) //
Math.clz32(0b00100000000000000000000000000000) // 2
//上面代码中,0的二进制形式全为0,所以有32个前导0;1的二进制形式是0b1,只占1位,所以32位之中有31个前导0;1000的二进制形式是0b1111101000,一共有10位,所以32位之中有22个前导0 //左移运算符(<<)与Math.clz32方法直接相关
Math.clz32() //
Math.clz32() //
Math.clz32( << ) //
Math.clz32( << ) //
Math.clz32( << ) //
对于小数,Math.clz32
方法只考虑整数部分;
对于空值或其他类型的值,Math.clz32
方法会将它们先转为数值,然后再计算。
5、Math.imul
Math.imul
方法返回两个数以32位带符号整数形式相乘的结果,返回的也是一个32位的带符号整数。
之所以需要部署这个方法,是因为JS有精度限制,超过2的53次方的值无法精确表示。这就是说,对于那些很大的数的乘法,低位数值往往都是不精确的,Math.imul
方法可以返回正确的低位数值。
6、Math.fround
Math.fround方法返回一个数的单精度浮点数形式。
对于整数来说,Math.fround
方法返回结果不会有任何不同,区别主要是那些无法用64个二进制位精确表示的小数。这时,Math.fround
方法会返回最接近这个小数的单精度浮点数
//对于没有部署这个方法的环境,可以用下面的代码模拟
Math.fround = Math.fround || function(x) {
return new Float32Array([x])[];
};
7、Math.hypot
Math.hypot
方法返回所有参数的平方和的平方根。如果参数不是数值,Math.hypot
方法会将其转为数值。只要有一个参数无法转为数值,就会返回NaN。
Math.hypot(, ); //
Math.hypot(, , ); // 7.0710678118654755
//3的平方加上4的平方,等于5的平方
8、ES6新增了4个对数相关方法
Math.expm1(x)
返回ex - 1,即Math.exp(x) - 1
Math.log1p(x)
方法返回1 + x
的自然对数,即Math.log(1 + x)
。如果x
小于-1,返回NaN
Math.log10(x)
返回以10为底的x
的对数。如果x
小于0,则返回NaN
Math.log2(x)
返回以2为底的x
的对数。如果x
小于0,则返回NaN
9、ES6新增了6个双曲函数方法
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)
ES6里关于数字的拓展的更多相关文章
- ES6里关于作用域的拓展:块级作用域
过去,javascript缺乏块级作用域,var声明时的声明提升.属性变量等行为让人困惑.ES6的新语法可以帮助我们更好地控制作用域. 一.var声明 1.变量提升:var声明会发生“变量提升”现象, ...
- ES6里关于函数的拓展(三)
一.箭头函数 在ES6中,箭头函数是其中最有趣的新增特性.顾名思义,箭头函数是一种使用箭头(=>)定义函数的新语法,但是它与传统的JS函数有些许不同,主要集中在以下方面: 1.没有this.su ...
- ES6里关于类的拓展(一)
大多数面向对象的编程语言都支持类和类继承的特性,而JS却不支持这些特性,只能通过其他方法定义并关联多个相似的对象,这种状态一直延续到了ES5.由于类似的库层出不穷,最终还是在ECMAScript 6中 ...
- ES6里关于函数的拓展(二)
一.构造函数 Function构造函数是JS语法中很少被用到的一部分,通常我们用它来动态创建新的函数.这种构造函数接受字符串形式的参数,分别为函数参数及函数体 var add = new Functi ...
- ES6里关于字符串的拓展
一.子串识别 自从 JS 引入了 indexOf() 方法,开发者们就使用它来识别字符串是否存在于其它字符串中.ES6 包含了以下三个方法来满足这类需求: 1.includes():该方法在给定文本存 ...
- ES6里关于类的拓展(二):继承与派生类
继承与派生类 在ES6之前,实现继承与自定义类型是一个不小的工作.严格意义上的继承需要多个步骤实现 function Rectangle(length, width) { this.length = ...
- ES6里关于函数的拓展(一)
一.形参默认值 Javascript函数有一个特别的地方,无论在函数定义中声明了多少形参,都可以传入任意数量的参数,也可以在定义函数时添加针对参数数量的处理逻辑,当已定义的形参无对应的传入参数时为其指 ...
- ES6里关于正则表达式的拓展
一.构造函数 在 ES5 中,RegExp构造函数的参数有两种情况. 第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag) var regex = new RegExp('xy ...
- 进阶路上有你我-相互相持篇之ES6里箭头函数里的this指向问题
首先复习下普通函数里的this指向: function test(){ console.log(this) } test() 你会秒杀的毫无疑问的回答:window,针对普通函数:谁调用了函数 函数 ...
随机推荐
- P3456 [POI2007]GRZ-Ridges and Valleys
题意翻译 给定一个地图,为小朋友想要旅行的区域,地图被分为n*n的网格,每个格子(i,j) 的高度w(i,j)是给定的.若两个格子有公共顶点,那么他们就是相邻的格子.(所以与(i,j)相邻的格子有(i ...
- sql优化 in 和 not in 语句
WHY? IN 和 NOT IN 是比较常用的关键字,为什么要尽量避免呢? 1.效率低 可以参看我之前遇到的一个例子([小问题笔记(九)] SQL语句Not IN 效率低,用 NOT EXISTS试试 ...
- Linux Ubuntu mysql 乱码
进入mysql后,敲入命令status,就可以看到mysql的字符编码问题. 默认如下: Server characterset: latin1 Db characterset: lat ...
- HDU 1171Big Event in HDU(转01背包)
题意: 给你一组数,分成差距最小的两份A,B(A>=B) 分析: 转01背包 注意: 01背包用一维数组 不要用二维 二维数组若是开太大,内存超限,开太小,RE #include "c ...
- VIM使用技巧1
.命令是vim中很重要的一个命令,用法如下: 加入有一个文件vimtest.txt,内容如下: 1 Line one 2 Line two ...
- 非MFC工程中使用MFC库
目录(?)[-] 需求说明 常见问题 问题分析 参考解决方法 我的解决方案 Stdafxh的原理 需求说明 C++工程的类型有很多,从VS(或VC)可以看到常见的有:Win32 Console A ...
- mogadm修改硬盘状态
#查看主机序列mogadm host list #查看空间快满的分区 df -h#检查硬盘序列和状态ls -l /data/mogile_data/ #查看mogadm目录下软链接的目录对应的分区 # ...
- 【linux高级程序设计】(第十六章)网络服务器应用设计
xinetd服务介绍 xinetd是Linux下的一个网络守候进程,用来统一管理网络负载不大的一组小型网路服务. 一些小型的网络服务,比如时间,telnet服务,不以守候进程出现,而是让xinetd服 ...
- hdu 5124(区间更新+单点求值+离散化)
lines Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- Python与数据结构[0] -> 链表/LinkedList[0] -> 单链表与带表头单链表的 Python 实现
单链表 / Linked List 目录 单链表 带表头单链表 链表是一种基本的线性数据结构,在C语言中,这种数据结构通过指针实现,由于存储空间不要求连续性,因此插入和删除操作将变得十分快速.下面将利 ...