阅读 509

最全 ECMAScript 攻略之 ES2018-ES9

Promise.prototype.finally.

许多promise第三方库都有一个finally方法,用于在promise结束(不管成功还是失败)时的回调。

常见的场景是

  • 关闭数据请求时的laoding状态
  • 不管前面的操作成功或是失败,最后都要执行一个指定的回调函数操作

现在我们的官方Promise标准已经支持了finally()方法.用于指定不管 Promise 对象最后状态如何,都会执行的操作。

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
复制代码

上面代码中,不管 promise 最后的状态,在执行完thencatch指定的回调函数以后,都会执行finally方法指定的回调函数。

更加详细内容请参考

按顺序完成异步操作(Asynchronous Iteration)

实际开发中,经常遇到一组异步操作,需要按照顺序完成。比如,依次远程读取一组 URL,然后按照读取的顺序输出结果。

场景: 如果你有一堆异步或普通函数都返回 promise,要求你一个接一个地执行,怎么办?

async function logInOrder(urls) {
  // 并发读取远程URL
  const textPromises = urls.map(async (url) => {
    const response = await fetch(url);
    return response.text();
  });

  // 按次序输出
  for (const textPromise of textPromises) {
    console.log(await textPromise);
  }
}
复制代码
async function getData() {
  const promises = [fetch("url1"), fetch("url2"), fetch("url3"), fetch("url4")];
  for (const item of promises) {
    // 打印出promise
    console.log(item);
  }

  for await (const item of promises) {
    // 打印出请求的结果
    console.log(item);
  }
}
复制代码

区别

async function printFiles() {
  const files = await getFilePaths();

  for (const file of files) {
    const contents = await fs.readFile(file, "utf8");
    console.log(contents);
  }
}
复制代码
async function printFiles() {
  const files =

  for (const file of await files) {
    console.log(file);
  }
}
复制代码
async function printFiles() {
  const files = await getFilePaths();

  await Promise.all(
    files.map(async (file) => {
      const contents = await fs.readFile(file, "utf8");
      console.log(contents);
    }),
  );
}
复制代码

ES 入门-顺序异步操作


为对象支持扩展运算符(Rest/Spread Properties.)

ES6 为数组引入了扩展运算符的写法, 在 ES2018 中,为对象也引入了此写法

const obj = { a: "a", b: "b", c: "c", d: "d", e: "e" };

// 对象解构
const { a, b, c, ...rest } = obj;

// 组成新对象
const newObj = { a, ...rest };
复制代码
// bad 👴
const test1 = this.data.test1;
const test2 = this.data.test2;
const test2 = this.data.test3;

// better 👶
const { test1, test2, test3 } = this.data;
复制代码

更加详细内容请参考

解除模板字面量限制(Lifting template literal restriction).

ES2018 放松了对标签模板里面的字符串转义的限制。如果遇到不合法的字符串转义,就返回undefined,而不是报错,并且从raw属性上面可以得到原始字符串。

function tag(strs) {
  strs[0] === undefined
  strs.raw[0] === "\\unicode and \\u{55}";
}
tag`\unicode and \u{55}`
复制代码

上面代码中,模板字符串原本是应该报错的,但是由于放松了对字符串转义的限制,所以不报错了,JavaScript 引擎将第一个字符设置为undefined,但是raw属性依然可以得到原始字符串,因此tag函数还是可以对原字符串进行处理。

正则之 s 修饰符:dotAll 模式-(s (dotAll) flag for regular expressions).

ES2018 引入 s修饰符,使得.可以匹配任意单个字符。

让点可以真正匹配任意单个字符

const reg = /./;
console.log(reg.test("5")); // true
console.log(reg.test("x")); // true
console.log(reg.test("\n")); // 换行符 false
console.log(reg.test("\r")); // 回车 false
console.log(reg.test("\u{2028}")); // 行分隔符 false
console.log(reg.test("\u{2029}")); // 段分隔符 false
const reg2 = /./s;
console.log(reg2.test("5")); // true
console.log(reg2.test("x")); // true
console.log(reg2.test("\n")); // true
console.log(reg2.test("\r")); // true
console.log(reg2.test("\u{2028}")); // true
console.log(reg2.test("\u{2029}")); // true
复制代码
/foo.bar/s.test("foo\nbar"); // true
复制代码

这被称为dotAll模式,即点(dot)代表一切字符。所以,正则表达式还引入了一个dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。

ES 入门-修饰符:dotAll 模式

正则之具名组匹配(RegExp named capture groups)

ES2018 引入了具名组匹配(Named Capture Groups),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。

ES2018 的案例

const date = /(\d{4})-(\d{2})-(\d{2})/.exec("2020-01-01");
console.log("date", date);
复制代码

20210519153509

这里 group 是没有数据的

通过 ?<>来设置 group 的 key

最新的案例

const reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
console.log(reg.exec('2020-02-01'))\
const groups = reg.exec('2020-02-01').groups
const {year, month, day} = groups
console.log(year, month, day) // 2020 02 01
复制代码

20210519153546

const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

const matchObj = RE_DATE.exec("1999-12-31");
const year = matchObj.groups.year; // "1999"
const month = matchObj.groups.month; // "12"
const day = matchObj.groups.day; // "31"
复制代码

ES 入门-修饰符:具名组匹配

正则之后行断言(RegExp Lookbehind Assertions.)

ES2018 引入后行断言

“后行断言”指: x只有不在y后面才匹配,必须写成/(?<!y)x/。比如,只匹配不在美元符号后面的数字,要写成/(?<!\$)\d+/

/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill')  // ["100"]
/(?<!\$)\d+/.exec('it’s is worth about €90')                // ["90"]
复制代码

使用后行断言进行字符串替换。

const RE_DOLLAR_PREFIX = /(?<=\$)foo/g;
"$foo %foo foo".replace(RE_DOLLAR_PREFIX, "bar");
// '$bar %foo foo'
复制代码

ES 入门-后行断言

Unicode 属性类(RegExp Unicode Property Escapes)

ES2018 引入了一种新的类的写法\p{...}\P{...},允许正则表达式匹配符合 Unicode 某种属性的所有字符。

Unicode 属性转义在正则表达式中可使用\p 表示匹配,使用\P 表示不匹配

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

// 匹配所有空格
const reg = /\p{White_Space}/;

// 匹配所有的箭头字符
const regexArrows = /^\p{Block=Arrows}+$/u;
regexArrows.test("←↑→↓↔↕↖↗↘↙⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙⇧⇩"); // true
复制代码

ES 入门-Unicode 属性类

最后

文章浅陋,欢迎各位看官评论区留下的你的见解!

觉得有收获的同学欢迎点赞,关注一波!

good

往期文章

文章分类
前端
文章标签