数值的扩展
二进制和八进制表示法
ES6 提供了二进制和八进制数值的新写法,分别用 0b(oB) 和 0o(0O)表示。
将 0b 和 0o 前缀的数字转化成十进制,用 Number() 方法。
Number('0b11'); // 3
Number('0011'); // 9
Number.isFinite() Number.isNaN()
Number.isFinite() 用来检查数值是否为有限的。
Number.isFinite(1); // true
Number.isFinite('15'); // false
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite(''); // false
Number.isFinite(true); // false
参数类型不是数值,一律返回 false。
Number.isNaN()
略...
Number.parseInt() Number.parseFloat()
将全局方法 parseInt() parseFloat() 移植到 Number 对象上。
Number.isInteger()
判断一个数值是否为整数。
Number.isInteger(20); // true
Number.isInteger(20.1); // false
Number.isInteger(20.0); // true
// 精度问题 产生误判
Number.isInteger(3.0000000000000002); // true
如果对数据精度的要求较高,不建议使用Number.isInteger()判断一个数值是否为整数。
Number.EPSILON
略
安全整数和 Number.isSafeInteger()
JavaScript 能准确表示的整数范围在 -2^53
和 2^53
之间,超过这个范围无法精确表示。
Math.pow(2, 53); // 9007199254740992
Math.pow(2, 53) + 1; // 9007199254740992
ES6 引入了 Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER,用来表示这两个范围的上下限。
Number.MAX_SAFE_INTEGER; // 9007199254740991
Number.MIN_SAFE_INTEGER; // -9007199254740991
Number.isSafeInteger 用来判断一个整数是否落在这个范围内。
Number.isSafeInteger('a'); // false
Number.isSafeInteger(1); // true
Number.isSafeInteger(null); // false
Number.isSafeInteger(NaN); // false
Number.isSafeInteger(Infinity); // false
Number.isSafeInteger(-Infinity); // false
Number.isSafeInteger(1); // true
Number.isSafeInteger(1.2); // false
Number.isSafeInteger(Number.MAX_SAFE_INTEGER); // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // false
Number.isSafeInteger(Number.MIN_SAFE_INTEGER); // true
Number.isSafeInteger(Number.MIN_SAFE_INTEGER - 1); // false
Number.isSafeInteger 的实现:
Number.isSafeInteger = (number) => {
return (typeof number === 'number' &&
Math.round(number) === number &&
Number.MIN_SAFE_INTEGER <= number &&
number <= Number.MAX_SAFE_INTEGER);
}
注意:不止要验证计算结果,还要验证每个值。
Math.pow(2, 53); // 9007199254740992
Math.pow(2, 53) + 1; // 9007199254740992
Number.isSafeInteger(9007199254740993); // false
Number.isSafeInteger(990); // true
console.log(9007199254740993 - 990); // 9007199254740002 应该是 9007199254740003
Number.isSafeInteger(9007199254740993 - 990); // true
Math 对象的扩展
Math.trunc()
去除一个数的小数部分,保留整数部分。
Math.trunc(1.1); // 1
Math.trunc(-1.1); // -1
Math.trunc(0.1); // 0
Math.trunc(-0.1); // -0
非数值,使用 Number 方法在内部先转为数值。
Math.trunc('1.11'); // 1
Math.trunc(true); // 1
Math.trunc(false); // 0
Math.trunc(null); // 0
Math.trunc(''); // 0
空值和无法截取整数的值,返回 NaN。
Math.trunc('foo'); // NaN
Math.trunc(NaN); // NaN
Math.trunc(); // NaN
Math.trunc(undefined); // NaN
模拟实现:
Math.trunc = Math.trunc || function(val) {
return val < 0 ? Math.ceil(val) : Math.floor(val);
}
Math.sign()
判断一个数是正数、负数还是零。
返回结果:
- 参数是正数,返回 +1
- 参数是负数,返回 -1
- 参数是0,返回 +0
- 参数是-0,返回 -0
- 其他值,返回 NaN
const { log } = console;
log(Math.sign(6)); // 1
log(Math.sign(-6)); // -1
log(Math.sign(0)); // 0
log(Math.sign(-0)); // -0
log(Math.sign(NaN)); // NaN
对于非数值,会先转换为数值。
const { log } = console;
log(Math.sign('')); // 0
log(Math.sign(false)); // 0
log(Math.sign(true)); // 1
log(Math.sign('test')); // NaN
log(Math.sign('9')); // 1
log(Math.sign(null)); // 0
log(Math.sign(undefined)); // NaN
log(Math.sign()); // NaN
模式实现:
const { log } = console;
Math.sign = Math.sign || function (x) {
x = +x;
if (x === 0 || isNaN(x)) {
return x;
}
return x > 0 ? 1 : -1;
}
log(Math.sign(2)); // 1
log(Math.sign(0)); // 0
log(Math.sign(-2)); // -1
log(Math.sign(false)); // 0
Math.cbrt()
用于计算一个数的立方根。
const { log } = console;
log(Math.cbrt(1)); // 1
log(Math.cbrt(-1)); // -1
log(Math.cbrt(0)); // 0
log(Math.cbrt(8)); // 2
log(Math.cbrt(-8)); // -2
log(Math.cbrt(NaN)); // NaN
// 对于非数值,先转换成数值
log(Math.cbrt('8')); // 2
log(Math.cbrt(null)); // 0
log(Math.cbrt('foo')); // NaN
模拟实现:
Math.cbrt = function(x) {
const y = Math.pow(Math.abs(x), 1/3);
return x > 0 ? y : -y;
}
log(Math.cbrt(8)); // 2
Math.clz32()
略...
Math.imul()
略...
Math.fround()
略...
Math.hypot()
返回所有参数的平方和的平方根。
Math.hypot(3, 4); // 5 Math.sqrt(Math.pow(3, 2) + Math.pow(4, 2))
Math.hypot(-3); // 3
Math.hypot(NaN); // NaN
Math.hypot(3, 4, 'foo'); // NaN
对数方法
基础知识:
ax = N; // x 叫做以 a 为底 N 的对数
x = logaN
Math.exp(x) 即 ex,其中 e 是自然对数的底数。
Math.expm1()
返回 ex - 1,即 Math.exp(x) - 1
模拟实现:
Math.expm1 = Math.expm1 || function(x) {
return Math.exp(x) - 1;
}
Math.log1p()
Math.log() 与 Math.exp() 相反。
Math.exp(x) 求的是 ex 的结果,Math.log(x) 求的是 e 的多少次方等于 x。
Math.log1p(x) 即 Math.log(1 + x)
如果 x 小于 -1,返回 NaN。
Math.log10()
Math.log10(x) => x = log10N,求的是 N 的值。
10x = N; (反过来求 N) --> Math.log10(x)
101 = 10; => Math.log10(10) = 1;
模拟实现:
Math.log10 = Math.log10 || function(x) {
return Math.log(x) / Math.LN10;
}
Math.log2()
Math.log2(x) 返回以2为底x的对数。
23 = 8;
Math.log2(8); // 3
双曲函数方法
新增 6 个双曲函数方法。
- Math.sinh()
- Math.cosh()
- Math.tanh()
- Math.asinh()
- Math.acosh()
- Math.atanh()
指数运算符
log(2 ** 2); // 4
log(3 ** 2); // 9
特点:从最右边开始算。
log(2 ** 1 ** 3); // 2 --> 2的(1的三次方)次方。 相当于 Math.pow(2, Math.pow(1, 3))
log(2 ** 2 ** 3); // 256 相当于 Math.pow(2, Math.pow(2, 3))
指数运算符可以与等号结合,形成新的赋值运算符。
let a = 2;
a **= 2;
log(a); // 4