数值的扩展

二进制和八进制表示法

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^532^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
Last Updated: 6/4/2019, 8:05:48 PM