复习ES(6-11)语法之ES9

目录

异步迭代

  • for-await-of
  • Symbol.asyncIterator

for...of循环用于遍历同步的 Iterator 接口。

function getPromise(time) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        value: time,
        done: false,
      });
    }, time);
  });
}
const arr = [getPromise(1000), getPromise(2000), getPromise(3000)];
for (let item of arr) {
  console.log(item); // 状态都是pending Promise { <pending> }
}

新引入的for await...of循环,则是用于遍历异步的 Iterator 接口。Symbol.asyncIterator依然遵守迭代器协议

arr[Symbol.asyncIterator] = function () {
  let nextIndex = 0;
  return {
    next() {
      return nextIndex < arr.length
        ? arr[nextIndex++]
        : Promise.resolve({
            value: undefined,
            done: true,
          });
    },
  };
};
async function test() {
  for await (let item of arr) {
    console.log(item); // 状态都是pending Promise { <pending> }
  }
}
test();

正则表达式扩展

  • dotAll

正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是有两个例外。一个是四个字节的 UTF-16 字符,这个可以用u修饰符解决;另一个是行终止符

所谓行终止符,就是该字符表示一行的终结。以下四个字符属于“行终止符”。

  • U+000A 换行符(\n
  • U+000D 回车符(\r
  • U+2028 行分隔符(line separator)
  • U+2029 段分隔符(paragraph separator)
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

ES2018 引入s修饰符,使得.可以匹配任意单个字符。这被称为dotAll模式,即点(dot)代表一切字符。

const reg = /./s;
console.log(reg.test("5")); // true
console.log(reg.test("x")); // true
console.log(reg.test("\n")); // true
console.log(reg.test("\r")); // true
console.log(reg.test("\u{2028}")); // true

所以,正则表达式还引入了一个dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。

const reg = /./;
console.log(reg.dotAll); // false


const reg = /./s;
console.log(reg.dotAll); // true
  • 具名组分配

正则表达式使用圆括号进行组匹配。正则表达式里面有三组圆括号。使用exec方法,就可以将这三组匹配结果提取出来。

const date = /(\d{4})-(\d{2})-(\d{2})/.exec("2023-07-10");
console.log(date);
console.log(date[1]);
console.log(date[2]);
console.log(date[3]);

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

“具名组匹配”在圆括号内部,模式的头部添加“问号 + 尖括号 + 组名”,然后就可以在exec方法返回结果的groups属性上引用该组名。

const date = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/.exec("2023-07-10");
console.log(date.groups.year);
console.log(date.groups.month);
console.log(date.groups.day);
  • 后行断言

“先行断言”指的是,x只有在y前面才匹配,必须写成/x(?=y)/

“先行否定断言”指的是,x只有不在y前面才匹配,必须写成/x(?!y)/

const str = "zzzapple";
console.log(str.match(/zzz(?=apple)/));
console.log(str.match(/zzz(?=banana)/)); // null
console.log(str.match(/zzz(?!banana)/));

“后行断言”正好与“先行断言”相反,x只有在y后面才匹配,必须写成/(?<=y)x/

“后行否定断言”则与“先行否定断言”相反,x只有不在y后面才匹配,必须写成/(?<!y)x/

console.log(str.match(/(?<=zzz)apple/));
console.log(str.match(/(?<=zzz)banana/)); // null
console.log(str.match(/(?<!zzz)apple/)); // null

对象扩展

对象的扩展运算符(...)用于取出参数对象的所有可遍历属性,不是引用而是真正拷贝到当前对象之中。

const obj1 = {
  name: "zzz",
};
const obj2 = {
  age: 18,
};
const obj = {
  ...obj1,
  ...obj2,
};
console.log(obj); // { name: 'zzz', age: 18 }
obj.age = 22;
console.log(obj2.age); // 18

如果合并2个对象有相同属性,后者属性会取代前者。

const obj1 = {
  name: "zzz",
  age: 34,
};
const obj2 = {
  age: 18,
};
const obj = {
  ...obj1,
  ...obj2,
};
console.log(obj); // { name: 'zzz', age: 18 }

可以通过rest参数提取对象中的属性

const obj = {
  name: "zzz",
  age: 18,
  lang: "zh-CN",
};
const { name, ...rest } = obj;
console.log(name); // zzz
console.log(rest); // { age: 18, lang: 'zh-CN' }

Promise.prototype.finally()

finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("success");
    // reject('fail')
  }, 1000);
})
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  })
  .finally(() => {
    console.log("finally");
  });

放松模板字符串文字限制

const foo = (arg) => {
  console.log(arg);
};
foo`\u{61} and \unicode`;

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

posted @ 2023-07-10 21:33  小风车吱呀转  阅读(15)  评论(0编辑  收藏  举报