ES2018(ES9)新特性

本篇文章介绍ECMAScript 2018(ES9)的新特性,来看看怎么使用它们。

async/await 异步迭代

ES8为我们带来 async/await,使我们能在同步的写法中执行异步函数,但是在循环中:

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

上面代码执行不符合预期,循环本身依旧保持同步,并在在内部异步函数之前全部调用完成。

ES2018引入异步迭代器(asynchronous iterators),使得 await 可以和 for...of 循环一起使用,以串行的方式运行异步操作。

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

Promise.finally()

ES6为我们带来了 Promise,但是它的结果要么成功 then 要么失败 catch,使得我们的一些逻辑,如执行状态修改,结束回调都得在两边写一遍。

选择有了 finally(),逻辑只可以放在一个地方了,这有点像以前 jQuery ajaxcomplete

return new Promise((reslove, reject) => {
  // ...
}).then((res) => {
  // reslove
}).catch((err) => {
  // reject
}).finally(() => {
  // complete
});

finally()没有参数传入。

Rest/Spread 属性

ES2015引入了Rest参数和扩展运算符。当时三个点 ... 仅用于数组。

Rest 参数语法允许我们将一个剩余参数表示为一个数组。

function foo(a, b, ...rest) {
  // a = 1
  // b = 2
  // rest = [3, 4, 5]
}

foo(1, 2, 3, 4, 5);

展开操作符则是将数组转换成可传递给函数的单独参数。

const nums = [1, 2, 3, 4, 5];
Math.max(...nums));  // 5

现在对象也可以使用它们了。

function foo({ a, b, ...rest }) {
  // a = 1
  // b = 2
  // rest = { c: 3, d: 4, e: 5 
}

foo({
  a: 1,
  b: 2,
  c: 3,
  d: 4,
  e: 5
}); 
const object = {
  a: 1,
  b: 2,
  c: 3,
  d: 4,
  e: 5
};

const { a, ...rest } = object;
// a = 1
// b = 2
// rest = { c: 3, d: 4, e: 5 }

跟数组一样,Rest参数只能在声明的结尾处使用。

正则表达式 s(dotAll模式)标记

在正则中,. 可以匹配任意字符,除了换行符。

/hello.es9/.test('hello\nes9');  // false

ES2018引入了dotAll模式,通过使用标记s选项,.就可以匹配换行符。

/hello.es9/s.test('hello\nes9');  // true

正则表达式 Unicode 转义

目前在正则中,可以通过字符集的名称来匹配字符。如s代表空白

/^\s+$/u.test(' ');  // true

在ES2018添加了Unicode属性转义,形式为\p{...}\P{...},在正则表达式中使用标记u(unicode) 选项。

/^\p{White_Space}+$/u.test(' ')       // true 空格
/^\p{Script=Greek}+$/u.test('μετά')   // true 希腊字母
/^\p{Script=Latin}+$/u.test('Grüße')  // true 匹配拉丁字母
/^\p{Surrogate}+$/u.test('\u{D83D}')  // true 匹配单独的替代字符

lookbehind 反向断言

目前JavaScript在正则表达式中支持先行断言(lookahead)。这意味着匹配会发生,但是断言没有包含在整个匹配字段中。

如匹配字符串“10 hours”中紧跟着是”hours”的数字:

const reg = /\d+(?= hours)/u;
const matched = reg.exec('10 hours');
matched[0];  // 42

匹配字符串“10 minutes”中紧跟着不是”hours”的数字:

const reg = /\d+(?! hours)/u;
const matched = reg.exec('10 minutes');
matched[0];  // 42

ES2018引入以相同方式工作但是匹配前面的反向断言(lookbehind)。

匹配字符串“hours10”中”hours”后面的数字:

const reg = /(?<=hours)\d+/u;
const matched = reg.exec('hours10');
matched[0];  // 10

匹配字符串“minutes10”中数字前面不是“hours”:

const reg = /(?

Named capture groups 正则表达式命名捕获组

目前,正则表达式中小括号匹配的分组是通过索引编号的:

const reg = /(\d{4})-(\d{2})-(\d{2})/u;
const matched = reg.exec('2018-12-31');
matched[0];  // 2018-12-12
matched[1];  // 2018
matched[2];  // 12
matched[3];  // 31

代码可读性较差,并且改变正则表达式的结构有可能改变匹配对象的索引。

ES2018允许命名捕获组使用符号?, 可以指定小括号中匹配内容的名称放在groups里,这样可以提高代码的可读性。

const reg = /(?\d{4})-(?\d{2})-(?\d{2})/u;
const matched = reg.exec('2018-12-31');
matched.groups.year;   // 2018
matched.groups.month;  // 12
matched.groups.day;    // 31

命名捕获组也可以使用在replace()方法中。例如将日期转换为“年月日”格式:

const reg = /(?\d{4})-(?\d{2})-(?\d{2})/u;
'2018-12-31'.replace(reg, '$年$月$日');  // 2018年12月31日

非转义序列的模板字符串

ES2018 移除对 ECMAScript 在带标签的模版字符串中转义序列的语法限制。

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

参考资料

  • What’s New in ES2018

合集

  • ES2021(ES12)新特性解读
  • ES2020(ES11)带来的新特性
  • ES2019(ES10)带来的9个新特性
  • ES2018(ES9)新特性
  • ES2017(ES8)新特性
  • ES2016(ES7)新特性

你可能感兴趣的:(ES2018(ES9)新特性)