之前出了个《30分钟带你掌握ES7、ES8》的文章,现在2018年11月已经接近尾声,ECMA联盟的TC39组织已经正式通过ES9(ES2018)提案,写入ECMASCRIPT标准规范。
那么接下来,请跟我一起学习ES9(ES2018)。
阅读本文依然是有前置知识储备的:

  • 不会ES3、ES4、ES5的同学,请去火狐浏览器的开发者中心:Mozilla的Web开发者文档,进行学习。
  • 不会ES6的同学,请买一本阮一峰老师的《ES6标准入门》照书上一步一步来即可。(可以去github仓库看下,最骚的是,阮老师push着、push着,就把一本ES6写成了ES678……)
  • 不会ES7、ES8的同学,请看我之前的文章,传送门:30分钟带你掌握ES7&ES8

另外需要注意的是:
目前的ES9提案可能在stage-4阶段,各大浏览器厂商都还未做到完全的实现,不过未来肯定是会实现的。(反正有babel的编译我知道你们并不会在乎这点的)

接下来就是正文啦:

  1. 异步迭代 async for await of
    之前我们在for循环里写异步代码,会直接在循环完以后才执行5遍代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    for(var i = 0; i < 5; i++) {
    setTimeout(function() {
    console.log(i);
    })
    }
    /* 最后输出的是: 5 5 5 5 5 */

    /* 那么有了异步迭代之后会怎样呢? */
    const arr = [1, 2, 3, 4, 5];
    async function haha(arr) {
    for await (let i of arr) {
    setTimeout(function() {
    console.log(i);
    })
    }
    }
    /* 输出 1 2 3 4 5 */

是不是解决了很多手残党的痛点 /滑稽脸

  1. 成功与失败统一处理Promise结果 Promise.finally()
    以前我们使用ES6中的Promise的时候,需要在.then()方法的回调函数中编写成功后的代码,然后在.catch()方法的回调函数中编写失败后的代码。
    那如果你在成功和失败后的处理代码是一样的,那你就得写两遍……
    所以Promise.finally()方法应运而生,可以直接在.finally()方法的回调函数中编写成功于失败后都将执行的代码!
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    let count = () => { 
    return new Promise((resolve, reject) => {
    setTimeout(() => { resolve(100) }, 1000);
    }
    )}
    let list = () => {
    return new Promise((resolve, reject) => {
    setTimeout(() => { resolve([1, 2, 3]) }, 1000);
    }
    )}
    let getList = async () => {
    let c = await count()
    let l = await list()
    return { count: c, list: l }
    }
    getList().then(res => {
    console.log(res)
    }).catch(err => {
    console.log(err)
    }).finally(() => {
    console.log('finally')
    })

    /* 最后输出的结果:{count: 100, list: [1, 2, 3]} finally */

需要注意:finally方法会直接让程序忽视已经写下的then和catch方法!

  1. Rest/Spread 新版扩展运算符
    在ES6中,官方引入了”…”运算符(也叫扩展运算符、展开运算符、Rest参数)
    但是在ES9中,扩展运算符的功能得到了加强,不再是数组的专利,现在,对象也可以使用扩展运算符来进行展开。
    使用场景:
  • 浅拷贝:但是这种拷贝只能拷贝对象的可枚举自有属性。

    1
    obj2 = {...obj1}
  • 合并两个对象

    1
    2
    3
    const merge = { ...obj1, ...obj2}
    /* 等同于 */
    const merge = Object.assign({}, obj1, obj2);

接下来大部分是关于正则表达式的内容:
PS: 其实这个意义对于平常来说并不是特别大,你可以不学这几条正则的内容。

  1. 正则表达式命名捕获组(Regular Expression Named Capture Groups)
    1
    ?<name> exec match groups

解决痛点: 用来匹配正则的字符串,可能存在各单位之间的顺序改变导致match到的结果,索引变动的问题。
相当于给每个匹配到正则的小区块,定义成一个groups下边的唯一变量,以方便追踪,解决索引变动问题。

1
2
3
4
5
6
const catchDate = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const catchThem = catchDate.exec('2018-11-14');
//使用groups对象精准定位到年月日
console.log(catchThem.groups.year) /* 2018 */
console.log(catchThem.groups.month) /* 11 */
console.log(catchThem.groups.day) /* 14 */

  1. 正则表达式反向断言(lookbehind)
    1
    符号:?<=

目前的先行断言(lookahead)

1
2
3
const reLookahead = /\D(?=\d+)/;
const match = reLookahead.exec('$88');
console.log( match[0] ); // $

ES9的反向断言(lookbehind)

1
2
3
const reLookbehind = /(?<=\D)\d+/; 
const match = reLookbehind.exec('$88');
console.log( match[0] ); // 88

  1. 正则表达式dotAll模式
    正则的”.”表示匹配除回车以外的任何单字符,但是如果回车被转译成了”\n”,就匹配失败了。
    现在可以加个标记”s”来允许”\n”的出现。

    1
    2
    /a.b/.test('a\nb');   /* false */
    /a.b/s.test('a\nb'); /* true */
  2. 正则表达式Unicode转义(鸡肋)
    到目前为止,在正则表达式中本地访问 Unicode 字符属性是不被允许的。
    ES2018添加了 Unicode 属性转义——形式为\p{…}和\P{…},
    在正则表达式中使用标记 u (unicode) 设置,
    在\p块儿内,可以以键值对的方式设置需要匹配的属性而非具体内容。

    1
    2
    const reGreekSymbol = /\p{Script=Greek}/u;
    console.log(reGreekSymbol.test('π')); // true
  3. 非转义序列的模板字符串(鸡肋+1)
    ES2018 移除对 ECMAScript 在带标签的模版字符串中转义序列的语法限制。
    对没错,就只是移除了限制……而已。

ok,ES9到此就完事了,其实只学前三条就行了,后边的……我就呵呵了……