1.二进制和八进制表示法
- ES6提供二进制和八进制的新写法:
- 二进制:0b(或0B);
- 八进制:0o(或0O);
// 二进制:0b/0B
let res1 = (0b111110111 === 503);
console.log(res1); // true
// 八进制:0o/0O
let res2 = (0o767 === 503);
console.log(res2); // true
- ES5开始,严格模式下八进制数不允许使用前缀0表示;
// 严格模式下,不允许使用0前缀表示八进制数,需要用0o形式的前缀
// 非严格模式
(function () {
console.log(0o11 === 011); // true
})()
// 严格模式下
(function () {
"use strict"
console.log(0o11 === 011); // Octal literals are not allowed in strict mode.
})()
- 转换为十进制数:使用Number()方法;
// 转换为十进制数:使用number()方法
console.log(Number(0b111)); // 7
console.log(Number(0o111)); // 73
console.log(Number(0x111)); // 23
2.Number.isFinite()、Number.isNaN()
- Number.isFinite():用于检查一个数值是否为有限的;
Number.isFinite(1); // true
- ES5中可以用下列代码部署该方法:
// ES5中部署Number.isFinite()方法的代码
(function (global) {
// 这里没太看懂
var global_isFinite = global.isFinite;
// 自定义Number对象的isFinite属性
Object.defineProperty(Number,'isFinite',{
value : function (value) {
return typeof value === 'number' && global_isFinite(value);
},
configurable : true,
enumerable :false,
writable : true
})
})(this);
- Number.isNaN():用来检查一个值是否为NaN;
- 非NaN数值一律返回false;
Number.isNaN(NaN); // true
- ES5中可以用下列代码部署该方法:
// ES5中部署Number.isNaN()方法的代码
(function (global) {
// 这里没太看懂
var global_isNaN = global.isNaN;
// 自定义Number对象的isFinite属性
Object.defineProperty(Number,'isNaN',{
value : function (value) {
return typeof value === 'number' && global_isNaN(value);
},
configurable : true,
enumerable :false,
writable : true
})
})(this);
3.parseInt()和parseFloat()方法
- ES6将这两个方法移植到了Number对象上面,行为与原先保持一致;
- 这么做的目的是在于逐步减少全局性方法,使得JavaScript逐步模块化;
// ES6将这两个全局方法移植到了Number对象上
// ES5的写法
let res1 = parseInt("1.11"); // 1
let res2 = parseFloat("123.886#"); // 123.886
// ES6的写法
let res3 = Number.parseInt("1.111111"); // 1
let res4 = Number.parseFloat("12.12#@$"); // 12.12
4.Number.isInteger()方法
- 作用:判断一个值是否为整数;
- 在JavaScript内部,整数和浮点数是同样的存储方法,因此1和1.0被看做是同一个值;
- ES5中部署该方法的代码见p88;
// 该方法用于判断一个数是否是整数
let res1 = Number.isInteger(12.0); // true
let res2 = Number.isInteger(12); // true
5.Number.EPSILON
- ES6新增的一个极小的常量;
- 引入该常量的目的:为浮点数计算设置一个误差范围;
- 如果误差小于这个常量就可以认为得到的是正确的浮点数运算结果;
- 该常量的实质其实是一个可以接受的误差范围;
// Number.EPSILON 一个常量 用于设置误差范围
const res1 = Number.EPSILON;
console.log(res1.toFixed(30)); // 0.000000000000000222044604925031
// 例子 误差检查函数
function withinErrorMargin(left,right){
return Math.abs(right - left) < Number.EPSILON; // 计算结果与计算结果的目标值之差的绝对值与该常量
比较
}
console.log(withinErrorMargin(0.1 + 0.2 , 0.3)); // true
console.log(withinErrorMargin(0.1 + 0.3 , 0.3)); // false
6.安全整数和Number.isSafeInteger()
安全整数
- JavaScript中能表示的整数范围在正2的53次方到负2的53次方之间,超出这个范围就无法精确表示;
Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER
- 用于表示安全整数这个范围的上下限;
// Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER 表示安全整数范围的上下限
let res1 = Number.MAX_SAFE_INTEGER; // 9007199254740991
let res2 = Number.MIN_SAFE_INTEGER; // -9007199254740991
Number.isSafeInteger()方法
- 用于检测一个整数是否在安全整数的范围内(处于安全范围内的整数返回true,其他数据类型以及范围外的数据都返回false);
// Number.isSafeInteger() 用于检测整数是否在安全整数的范围内
let res3 = Number.isSafeInteger(Number.MAX_SAFE_INTEGER); // true
let res4 = Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // false
Number.isSafeInteger()方法实现原理
- 原理:仅需要将整数与范围边界作比较即可;
// Number.isSafeInteger()方法原理
function isSafeInteger(num) {
return (typeof num === "number" && Math.round(num) === num && Number.MAX_SAFE_INTEGER >= num &&
Number.MIN_SAFE_INTEGER <= num);
}
console.log(isSafeInteger(1)); // true
console.log(isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false
- 在实际使用该方法时,不仅仅需要检测最后的运算结果是否在安全整数范围内,同时也需要检测所有参与运算的整数;
- 检测两个运算数与结果的列子:
function trusty(left,right,result){
/*
left:参与运算的第一个整数
right:参与运算的第二个整数
result:运算结果
*/
if(Number.isSafeInteger(left) && Number.isSafeInteger(right) && Number.isSafeInteger(result)){
return result;
}
throw new RangeError("某一数值不在安全范围内!");
}
console.log(trusty(1,2,3)); // 3
7.Math对象的扩展
- ES6为Math新增了17个与数学相关的静态方法,只能在Math对象上调用;
Math.trunc()
- 用于去除小数部分,返回一个整数;
- 关于参数:
- 非数值:先转换为Number类型;
- 空值和无法截取整数的值:返回NaN;
// 1. Math.trunc() 去掉小数,返回一个整数
let res1 = Math.trunc(12.1212); // 12
let res2 = Math.trunc("123.321"); // 123 字符串先转换为Number
let res3 = Math.trunc(); // NaN
- 对于未部署Math.trunc()方法的环境,可以使用以下代码模拟:
// 兼容不支持ES6语法的浏览器
Math.trunc = Math.trunc || function(x){
// < 0 : 向上取整 > 0 向下取整
return x < 0 ? Math.ceil(x) : Math.floor(x);
}
Math.sign()
- 用于判断一个数是正数、负数、还是零;
- 非数值会先转换为Number类型;
- 返回值为以下有4种类型中的一个:
- 参数为正数:+1;
- 参数为负数:-1;
- 参数为0:0;
- 参数为-0:0;
- 参数为其他值:NaN;
// 2.Math.sign 方法:判断一个数是正数、负数、还是0
// 正数
let res4 = Math.sign(12); // 1
// 负数
let res5 = Math.sign(-12); // -1
// 0
let res6 = Math.sign(0); // 0
// -0
let res7 = Math.sign(-0); // 0
// NaN
let res8 = Math.sign(NaN); // NaN
- 对于未部署ES6的环境,可以用以下方法模拟:
// ES5语法模拟Math.sign()方法
Math.sign = Math.sign || function (x) {
x = +x; // 转换为数值
if(x === 0 || Math.isNaN(X)){
return x;
}
return x > 0 ? 1 : -1;
}
Math.cbrt()
- 该方法用于计算一个数的立方根;
// Math.cbrt() 计算立方根
let re1 = Math.cbrt(8); // 2
let re2 = Math.cbrt("test"); //NaN
- 对于未实现ES6语法的环境,可用以下方法来模拟:
// ES5模拟Math.cbrt()方法
Math.cbrt = Math.cbrt || function (x) {
return Math.pow(Math.abs(x),1/3); // Math.pow(a,b):返回a的b次幂结果
}
Math.clz32()
- 将参数转为 32 位无符号整数的形式,然后返回这个 32 位值里面有多少个前导 0;
// 4.Math.clz32() 将参数转换为32位二进制,并返回前补0的个数
let re3 = Math.clz32(1); // 31
- 对于小数,Math.clz32()只考虑整数部分;
// 对于小数 只考虑整数部分
let re4 = Math.clz32(1.22); // 31
- 左移运算符与Math.clz32()方法直接相关(左移运算能改变前补0的个数):
// 左移运算符与该方法的关系
let re5 = Math.clz32(1 << 1); // 30
- 空值和其他类型:先转换为Number类型;
Math.imul()
- 作用:返回两个数以32位带符号整数形式相乘的结果,返回的结果也是带符号的32位整数形式;
- 该方法等同于a*b的形式,但是为什么还需要Math.imul()方法?
- 因为JavaScript有精度限制,超过正负2的53次方的数值就无法精确表示,因此对于很大位数的乘法,其低位数值往往都是不准确的;
- 使用Math.imul()方法可以返回正确的低位数值;
// Math.imul() 求两个数32位无符号整数形式之积 并返回32位无符号整数形式的结果
let re1 = Math.imul(0x7fffffff, 0x7fffffff); // 1
Math.fround()
- 作用:返回一个数的单精度浮点数形式;
Math.hypot()
- 返回所有参数的平方和的平方根;
对数方法
Math.expm1()
- Math.expm1(x)返回 ex - 1,即Math.exp(x) - 1;
Math.log1p()
- Math.log1p(x)方法返回1 + x的自然对数,即Math.log(1 + x)。如果x小于-1,返回NaN。
Math.log10()
- Math.log10(x)返回以 10 为底的x的对数。如果x小于 0,则返回 NaN;
Math.log2()
- Math.log2(x)返回以 2 为底的x的对数。如果x小于 0,则返回 NaN。
双曲函数方法
- 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)
8.指数运算符
- 写法:**
- a**b:表示a的b次方;
a **= a;//等于 a=a*a
a ***= a;//等于 a=a*a*a
10.BigInt数据类型
- JavaScript 所有数字都保存成 64 位浮点数,这给数值的表示带来了两大限制。一是数值的精度只能到53个二进制位(相当于16个十进制位),大于这个范围的整数,JavaScript是无法精确表示的,这使得JavaScript不适合进行科学和金融方面的精确计算。二是大于或等于2的1024次方的数值,JavaScript 无法表示,会返回Infinity。
- 用来表示整数,没有位数的限制,任何位数的整数都能精确表示;
// BigInt 用来表示整数,没有位数限制,因此能精确表示任何位数
const a = 2172141653n;
const b = 15346349309n;
// BigInt 可以保持精度
a * b // 33334444555566667777n
// 普通整数无法保持精度
Number(a) * Number(b) // 33334444555566670000
- 为了与Number类型区分,BigInt类型需要加后缀n;
// BigInt类型需要加后缀n
// 普通数字
1n + 2n; // 3n
// 各种进制表示
0b1101n // 二进制
0o777n // 八进制
0xFFn // 十六进制
- BigInt类型与普通整数是两种值,两者并不相等;
// BigInt类型与普通整数是两种值,两者并不相等
(1n === 1); // false
- typeof对BingInt返回bigint;
// typeof对BingInt返回bigint
(typeof 1n); // bigint
- BinInt可以使用-号,但是不可以使用+号,会与asm.js冲突;
-42n // 正确
+42n // 报错
BigInt对象
- JavaScript 原生提供BigInt对象,可以用作构造函数生成 BigInt 类型的数值。转换规则基本与Number()一致,将其他类型的值转为 BigInt;
BigInt(123);// 123n
BigInt("123"); // 123n
BigInt(true); // 1n
BigInt(false); // 0n
- BigInt构造函数在使用时,必须有参数,且参数必须要可以转换为数值,否则会报错(如null、undefined等);
- 参数不可以是小数;
BigInt提供的方法
-
继承了Object对象的两个方法:
- BigInt.prototype.toString()
- BigInt.prototype.valueOf()
-
继承了Number对象的一个实例方法:
- BigInt.prototype.toLocaleString()
-
自身提供三个静态方法:
- 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。
-
转换规则:可以使用Boolean()、Number()和String()这三个方法,将 BigInt 可以转为布尔值、数值和字符串类型。
-
数学运算:
- 除了不带运算符的右移位运算符(>>>)和一元求和运算符(+),其他的都可以用;
- 不能与普通数值混合运算;