• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • ECMAScript 2018(ES9)新特性

    ECMAScript 2018(ES9)新特性:

    • 异步迭代:asyncawait
    • Promise方法::finally()。无论结果是 Resolved 或者是 Rejected 都会执行。
    • RestSpread操作符和对象构建。
    • 正则表达式:命名捕获组、反向断言、Unicode 属性转义。
    • 模板文字和带标签的模板文字。


    异步迭代:async、await

    在异步/等待过程中的某个时刻,您将尝试在同步循环内调用异步函数。

    async function process(array) {
      for (let i of array) {
        await doSomething(i);
      }
    }
    // 它不会起作用
    
    async function process(array) {
      array.forEach(async i => {
        await doSomething(i);
      });
    }
    // 它不会起作用
    

    循环本身保持同步,并且总是在它们的内部异步操作之前完成。ES2018 引入了异步迭代器,它与常规迭代器一样,只是方法返回一个 Promise。因此,关键字可以与循环一起使用以串行运行异步操作。

    async function process(array) {
      for await (let i of array) {
        doSomething(i);
      }
    }
    


    Promise.finally()

    在之前的 Promise 的调用链要么调用成功返回.then()方法,要么调用失败返回.catch()方法。在某些情况下,你想要在无论是成功还是失败,都运行同样的代码。例如实现清除、删除对话、关闭数据连接等操作。Promise.finally()允许你指定最终的逻辑。这为指定执行完 Promise 后,无论结果是 Resolved 或者是 Rejected 都需要执行的代码提供了一种方式。

    Promise.finally()法接受一个回调函数作为参数,由于无法知道 Promise 实例的最终状态,所以finally()的回调函数中不接收任何参数,它仅用于无论最终结果如何都要执行的情况。

    server.listen(0)
    .then(function (){})
    .catch(function (){})
    .finally(server.stop);
    
    function doSomething() {
      doSomething1()
      .then(doSomething2)
      .then(doSomething3)
      .catch(err => {
        console.log(err);
      })
      .finally(() => {
        // finish here!
      });
    }
    


    Rest/Spread操作符和对象构建

    Rest和Spread的操作符都是...,只不过使用的场景和目的不一样。Rest(展开)主要用在对象的解构,目前只支持对象的解构和不确定的参数描述。Spread(扩展)主要用在字面量对象的构建上。

    数组

    ES2015 为数组引入了 Rest(展开)参数和 Spread(扩展)运算符。

    restParam(1, 2, 3, 4, 5);
    function restParam(p1, p2, ...p3) {  
        // p1 = 1
        // p2 = 2
        // p3 = [3, 4, 5]
    }
    

    Spread 运算符以相反的方式工作,并将数组转换为可以传递给函数的单独参数。例如,给定任意数量的参数,返回最高值:Math.max()

    const values = [99, 100, -1, 48, 16];
    console.log( Math.max(...values) ); // 100
    


    对象

    ES2018 为对象解构提供了和数组一样的 Rest(展开)参数和 Spread(扩展)运算符。

    const myObject = {
      a: 1,
      b: 2,
      c: 3
    };
    
    const { a, ...x } = myObject;
    // a = 1
    // x = { b: 2, c: 3 }
    

    或者您可以使用它将值传递给函数。

    restParam({
      a: 1,
      b: 2,
      c: 3
    });
    
    function restParam({ a, ...x }) {
      // a = 1
      // x = { b: 2, c: 3 }
    }
    
    

    跟数组一样,Rest参数只能在声明的结尾处使用。此外,它只适用于每个对象的顶层,如果对象中潜逃对象则无法适用。扩展运算符可以在其他对象内使用。

    const obj1 = { a: 1, b: 2, c: 3 };
    const obj2 = { ...obj1, z: 26 };
    // obj2 is { a: 1, b: 2, c: 3, z: 26 }
    

    您可以使用 Spread 运算符来克隆对象,但请注意,您只能获得浅拷贝。如果属性包含另一个对象,则克隆将引用同一对象。obj2 ={...obj1};


    正则表达式

    命名捕获组

    JavaScript 正则表达式可以返回匹配对象-类似于数组的值,包含匹配的字符串。例如,要以 YYYY-MM-DD 格式解析日期:

    const
      reDate = /([0-9]{4})-([0-9]{2})-([0-9]{2})/,
      match  = reDate.exec('2018-04-30'),
      year   = match[1], // 2018
      month  = match[2], // 04
      day    = match[3]; // 30
    

    它很难阅读,并且更改正则表达式也可能会更改匹配对象索引。

    ES2018 允许在开始捕获括号后立即使用符号命名组。例如:?

    const
      reDate = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/,
      match  = reDate.exec('2018-04-30'),
      year   = match.groups.year,  // 2018
      month  = match.groups.month, // 04
      day    = match.groups.day;   // 30
    

    任何未匹配的命名组都将其属性设置为 undefined。

    命名捕获也可用于方法中。例如,将日期转换为美国 MM-DD-YYYY 格式:replace()

    const
      reDate = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/,
      d      = '2018-04-30',
      usDate = d.replace(reDate, '$<month>-$<day>-$<year>');
    


    反向断言

    JavaScript 目前支持正则表达式中的前瞻断言。这意味着必须进行匹配但不捕获任何内容,并且断言不包含在整个匹配的字符串中。例如,要从任何价格中捕获货币符号:

    const
      reLookahead = /\D(?=\d+)/,
      match       = reLookahead.exec('$123.89');
    
    console.log( match[0] ); // $
    

    ES2018 引入以相同方式工作但是匹配前面的反向断言。这样我就可以忽略货币符号,单纯的捕获价格的数字:

    const
      reLookbehind = /(?<=\D)\d+/, match = reLookbehind.exec('$123.89'); console.log( match[0] ); // 123.89
    

    以上是肯定反向断言,非数字\D必须存在。同样的,还存在否定反向断言,表示一个值必须不存在。例如:

    const
      reLookbehindNeg = /(?// null<、small>
    


    dotAll 模式

    正则表达式中.(点)匹配除回车外的任何单字符,标记s改变这种行为,允许行终止符的出现,例如:

    /hello.world/s.test('hello\nworld'); // true
    


    Unicode 属性转义

    到目前为止,还无法在正则表达式中本机访问 Unicode 字符属性。ES2018 在设置了u(Unicode)标志的正则表达式中,以\p{…}\p{…}的形式,添加 Unicode 属性转义。

    const reGreekSymbol = /\p{Script=Greek}/u;
    reGreekSymbol.test('π'); // true
    


    模板文字调整

    之前,\u开始一个 unicode 转义,\x开始一个十六进制转义,\后跟一个数字开始一个八进制转义。这使得创建特定的字符串变得不可能,例如 Windows文件路径C:\uuu\xxx\111

    ES2018 删除了与模板文字中的转义序列相关的所有语法限制。