字符串的扩展

新增方法

确定包含关系

  • includes(): 返回布尔值,表示是否找到了参数字符串,支持第二个参数,表示开始搜索的位置

    1
    2
    'hello world'.includes('llo')                 // => true
    'hello world'.includes('llo', 5) // => false
  • startsWith(): 返回布尔值,表示参数字符串是否在原字符串的头部,支持第二个参数,表示开始搜索的位置

    1
    2
    'hello world'.startsWith('llo')               // => false
    'hello world'.startsWith('llo', 2) // => true
  • endsWith(): 返回布尔值,表示参数字符串是否在原字符串的尾部,支持第二个参数,表示开始搜索的位置

    1
    2
    'hello world'.endsWith('llo')               // => true
    'hello world'.endsWith('llo', 2) // => true

重复

repeat()方法返回一个新的字符串,表示将原字符串重复n次

1
'abcd'.repeat(3)                        // => abcdabcdabcd

如果参数是小数,则先取整,取整后为负数或者Infinity则报错;参数为字符串则先转换为数字;NaN视为0

字符串补全

ES2017引入了字符串长度补全方法,padStart()用于头部补全,padEnd()用于尾部补全。

这两个方法可以接受两个参数,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串

可以用于提示字符串格式

1
'04-26'.padStart(10, 'YYYY-MM-DD')        // => YYYY-04-26
  • 如果原字符串的长度等于或大于最大长度,则字符串补全不生效,返回原字符串

    1
    2
    'abcd'.padStart(2, 'efg')                // => abcd
    'abcd'.padEnd(2, 'efg') // => abcd
  • 如果用来补全的字符串与原字符串,两者的长度之和超过了最大长度,则会截去超出位数的补全字符串

    1
    2
    'abcd'.padStart(6, 'efgh')                // => efabcd
    'abcd'.padEnd(6, 'efgh') // => abcdef
  • 如果省略第二个参数,默认使用空格补全长度

    1
    2
    'abcd'.padStart(6)                // => '  abcd'
    'abcd'.padEnd(6) // => 'abcd '

数值的扩展

二进制和八进制表示

ES6中二进制和八进制分别用前缀0b(或0B)和0o(或0O)表示

1
2
0b1101 === 13                       // => true
0o76 === 62 // => true

可以使用Number()方法将0b0o前缀的数值转为十进制

1
2
Number(0b1101)                      // => 13
Number(0o76) // => 62

Number对象上的新方法

  • Number.isFinite()用来检查一个数值是否是有限的,仅对数值有效,对于非数值一律返回false

    1
    2
    Number.isFinite(3.14)                 // => true
    Number.isFinite(Infinity) // => false

    ES5部署方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    (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);
  • Number.isNaN()用来检查一个数值是否为NaN,仅对NaN返回true,对于其他一律返回false

    1
    2
    Number.isNaN(NaN)                 // => true
    Number.isNaN(3.14) // => false

    ES5部署方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    (function (global) {

    var global_isNaN = global.isNaN;

    Object.defineProperty(Number, 'isNaN', {
    value: function isNaN(value) {
    return typeof value === 'number' && global_isNaN(value);
    },
    configurable: true,
    enumerable: false,
    writable: true
    });
    })(this);
  • ES6将全局方法parseInt()parseFloat()移植到Number对象上面,行为完全保持不变,目的是逐步减少全局性方法,使得语言逐步模块化

  • Number.isInteger()用来判断一个值是否为整数

    1
    2
    Number.isInteger(3.0)               // => true
    Number.isInteger('3.0') // => false

    ES5部署方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    (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);

    JavaScript中整数和浮点数用同样的存储方法,3.0和3被视为同一个值

  • Number.EPILSON是ES6在Number对象上新增的一个极小的常量

    1
    Number.EPILSON                // => 2.220446049250313e-16

    引入该常量的目的:为浮点数计算设置误差范围

  • 安全整数

    JavaScript能表示的整数范围在-253到253之间

    1
    Math.pow(2, 53) === Math.pow(2, 53) + 1       // => true
    • ES6引入Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER表示证书范围的上下界

      1
      2
      3
      Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1       // => true
      Number.MAX_SAFE_INTEGER === Math.pow(2, 53) // => false
      Number.MAX_SAFE_INTEGER === -Number.MIN_SAFE_INTEGER // => true
    • Number.isSafeInteger()用来判断一个整数是否在这个范围

      1
      2
      Number.isSafeInteger(3)                // => true
      Number.isSafeInteger('a') // => false

      函数实现:

      1
      2
      3
      4
      5
      6
      Number.isSafeInteger = function (n) {
      return typeof n === 'number' &&
      Math.round(n) === n &&
      Number.MIN_SAFE_INTEGER <= n &&
      Number.MAX_SAFE_INTEGER >= n;
      }

      使用时应验证参与运算的每个值,只验证结果可能会发生错误

      1
      2
      3
      4
      5
      6
      Number.isSafeInteger(9007199254740993)         // => false
      Number.isSafeInteger(990) // => true
      Number.isSafeInteger(9007199254740993 - 990) // => true
      // 9007199254740993 - 990
      // 返回结果 9007199254740002
      // 正确答案应该是 9007199254740003

      可以使用以下函数

      1
      2
      3
      4
      5
      6
      function trusty(left, right, result) {
      if (Number.isSafeInteger(left) && Number.isSafeInteger(right) && Number.isSafeInteger(result)) {
      return result;
      }
      throw new RangeError('Operation cannot be trusted');
      }

Math对象上的扩展

所有方法均为静态方法,只能在Math对象上调用

  • Math.trunc()用于去除一个数的小数部分;对于数字字符串,先转换为数字;对于空值和无法截取的值,返回NaN

    1
    2
    3
    4
    5
    6
    7
    Math.trunc(3.14)                  // => 3
    Math.trunc(-3.14) // => -3
    Math.trunc(-0.14) // => -0
    ---------------------------------------------
    Math.trunc('3.14') // => 3
    ---------------------------------------------
    Math.trunc('abd') // => NaN

    对于没有部署该方法的环境:

    1
    2
    3
    4
    5
    6
    7
    8
    Math.trunc = Math.trunc || function (x) {
    return x < 0 ? Math.ceil(x) : Math.floor(x);
    }
    -----------------------------------------------
    Math.trunc = Math.trunc || function(x) {
    x = +x;
    return (x - x % 1) || (!isFinite(x) || x === 0 ? x : x < 0 ? -0 : 0);
    };
  • Math.sign()用来判断一个数是正数,负数,还是0;对于非数值,会先将其转换为数值,否则返回NaN

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Math.sign(3.14)                 // => 1
    Math.sign(-3.14) // => -1
    -----------------------------------------
    Math.sign('3.14') // => 1
    -----------------------------------------
    Math.sign(0) // => 0
    Math.sign(-0) // => -0
    -----------------------------------------
    Math.sign('abc') // => NaN

    对于没有部署该方法的环境:

    1
    2
    3
    4
    5
    6
    7
    Math.sign = Math.sign || function (x) {
    x = +x; // 转换为数字
    if (x === 0 || isNaN(x)) {
    return x;
    }
    return x > 0 ? 1 : -1;
    }
  • Math.cbtr()用于计算一个数的立方根;对于非数值,会先将其转换为数值,否则返回NaN

    1
    2
    3
    4
    Math.cbrt(-8)                  // => -2
    -----------------------------------------
    Math.cbrt('8') // => 2
    Math.cbrt('asd') // => NaN

    对于没有部署该方法的环境:

    1
    2
    3
    4
    Math.cbrt = Math.cbrt || function (x) {
    var y = Math.pow(Math.abs(x), 1 / 3);
    return x < 0 ? -y : y;
    }
  • Math.clz32()用于返回一个数的32位无符号整数形式有多少个前导0;对于小数,只考虑整数部分;对于非数值,会先将其转换为数值,然后在计算

    1
    2
    3
    4
    5
    6
    7
    Math.clz32(1000)                // => 22
    Math.clz32(0b1000) // => 28
    Math.clz32(3.14) // => 30
    -----------------------------------------
    Math.clz32('asd') // => 32
    -----------------------------------------
    Math.clz32(true) // => 31

    对于没有部署该方法的环境:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Math.clz32 = Math.clz32 || function(value) {
    var value = Number(value) >>> 0;
    return value ? 32 - value.toString(2).length : 32;
    }
    -------------------------------------------------------
    // 另一种实现方法
    Math.clz32 = (function(log, LN2){
    return function(x) {
    if (x == null || x === 0) {
    return 32;
    }
    return 31 - (log(x >>> 0) / LN2 | 0);
    };
    })(Math.log, Math.LN2);
  • Math.imul()方法返回两个数以32位带符号整数形式相乘的结果;对于大数的乘法可以返回正确的低位数值

  • Math.fround()返回最接近的32位单精度浮点数形式;对于整数结果没有不同

    1
    2
    Math.fround(1)                  // => 1
    Math.fround(1.23) // => 1.2300000190734863

    对于没有部署该方法的环境:

    1
    2
    3
    4
    5
    Math.fround = Math.fround || (function (array) {
    return function(x) {
    return array[0] = x, array[0];
    };
    })(new Float32Array(1));
  • Math.hypot()返回所有参数平方和的平方根;对于非数值,会先将其转换为数值,否则返回NaN

    1
    2
    3
    4
    Math.hypot(3, 4)                // => 5
    Math.hypot(3, 4, 5) // => 7.0710678118654755
    Math.hypot() // => 0
    Math.hypot('a', 'b') // => NaN

    对于没有部署该方法的环境:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    Math.hypot = Math.hypot || function() {
    var y = 0,
    i = arguments.length;
    while (i--) {
    y += arguments[i] * arguments[i];
    }
    return Math.sqrt(y);
    };

    // 该方法有一个问题:
    // 在JS的双浮点数中可以表示的最大数字是number.max_value=1.797e+308
    // 如果你的数字大于1E154,取它们的平方将导致无穷大,从而破坏结果
    // 例如,math.sqrt(1e200*1e200+1e200*1e200)=infinity
    // 可以使用以下方法避免数字溢出或下溢

    Math.hypot = function (x, y) {
    var max = 0;
    var s = 0;
    for (var i = 0; i < arguments.length; i += 1) {
    var arg = Math.abs(Number(arguments[i]));
    if (arg > max) {
    s *= (max / arg) * (max / arg);
    max = arg;
    }
    s += arg === 0 && max === 0 ? 0 : (arg / max) * (arg / max);
    }
    return max === 1 / 0 ? 1 / 0 : max * Math.sqrt(s);
    };
  • 对数方法

    • Math.expm1() 返回 ex - 1,即Math.exp(x) - 1

      1
      2
      Math.expm1(1)                     // => 1.718281828459045
      Math.expm1(0) // => 0

      对于没有部署该方法的环境:

      1
      2
      3
      Math.expm1 = Math.expm1 || function(x) {
      return Math.exp(x) - 1;
      };
    • Math.log1p(x) 返回 ln(1 + x),即Math.log(1 + x);如果x小于-1,则返回NaN

      1
      2
      3
      4
      Math.log1p(1)                     // => 0.6931471805599453
      Math.log1p(0) // => 0
      Math.log1p(-1) // => -Infinity
      Math.log1p(-2) // => NaN

      对于没有部署该方法的环境:

      1
      2
      3
      Math.log1p = Math.log1p || function(x) {
      return Math.log(1 + x);
      };
    • Math.log10(x) 返回以10为底的x的对数;如果x小于0,则返回NaN

      1
      2
      3
      4
      Math.log10(1000)                  // => 3
      Math.log10(1) // => 0
      Math.log10(0) // => -Infinity
      Math.log10(-2) // => NaN

      对于没有部署该方法的环境:

      1
      2
      3
      Math.log10 = Math.log10 || function(x) {
      return Math.log(x) / Math.LN10;
      };
    • Math.log2(x) 返回以10为底的x的对数;如果x小于0,则返回NaN

      1
      2
      3
      4
      Math.log2(8)                     // => 3
      Math.log2(1) // => 0
      Math.log2(0) // => -Infinity
      Math.log2(-2) // => NaN

      对于没有部署该方法的环境:

      1
      2
      3
      Math.log2 = Math.log2 || function(x) {
      return Math.log(x) / Math.LN2;
      };
  • 双曲函数方法

    • Math.sinh(x) 返回x的双曲正弦

    • Math.cosh(x) 返回x的双曲余弦

    • Math.tanh(x) 返回x的双曲正切

    • Math.asinh(x) 返回x的反双曲正弦

    • Math.acosh(x) 返回x的反双曲余弦

    • Math.atanh(x) 返回x的反双曲正切

  • 指数运算符

    ES2016新增了指数运算符**,可以与等号结合为**=

    1
    2
    3
    4
    2 ** 3                      // => 8
    ----------------------------------------
    let a = 3;
    a **= 2; // => 9