for await of

异步操作集合的遍历

function Gen(time) {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(time), time)
    })
}
 
async function test() {
    let arr = [Gen(2000), Gen(100), Gen(3000)]
    for await (let item of arr) {
        console.log(Date.now(), item)
    }
}
test()
// for await of 需要 [Symbol.asyncIterator]
const obj = {
    count: 0,
    Gen(time) {
        return new Promise((resolve, reject) => {
        setTimeout(() => resolve({ done: false, value: time }), time)
    }),
    [Symbol.asyncIterator]() {
        let self = this
        return {
            next() {
                self.count++
                if (self.count < 4) {
                    return self.Gen(Math.random() * 1000)
                } else {
                    return Promise.resolve({
                        done: true,
                        value: undefined
                    })
                }
            }
        }
    }
}

更多内容详见:异步迭代器和异步可迭代协议

Promise

  • Promise.prototype.finally()

Object

对象的解构和扩展运算符

const o1 = { a: 1, b: 2 }
const o2 = { c: 3 }
 
const o3 = {
    ...o1,
    ...o2,
    a: 99,
    d: 4
}
 
o1.b = 100
console.log(o3) // { a: 99, b: 2, c: 3, d: 4 }
 
// 解构 + 剩余参数
const { a, ...rest } = o3

RegExp

dotAll

RegExp 中 . 匹配不了的字符:

  1. 4 位以上的 unicode
// 使用 u 修饰符解决
/𠮷{2}/.test('𠮷𠮷') // false
/𠮷{2}/u.test('𠮷𠮷') // true
  1. \n 等转译字符
// 使用 s 修饰符解决
/foo.bar/.test('foo\nbar') // false
/foo.bar/s.test('foo\nbar') // true

总结:/./us. 就全能了

const re1 = /foo.bar/
const re2 = /foo.bar/s
 
re1.dotAll // false
re2.dotAll // true
 
// --------------------------------
// 其他判断方法
const re = /foo.bar/usgi
re.flags // "gisu"

命名分组捕获

const t = '2019-06-07'.match(/(\d{4})-(\d{2})-(\d{2})/)
/*
{
    0: "2019-06-07"         // 完整匹配
    1: "2019"               // 第一个分组
    2: "06"                 // 第二个分组
    3: "07"                 // 第三个分组
    groups: undefined       // 分组
    index: 0                // 正则是从第几个字符匹配到的
    input: "2019-06-07"     // 输入字符串
    length: 4
}
*/
 
t[1] // 2019
t[2] // 06
t[3] // 07
// ES9 之前这样写,非常不清晰,不方便
 
// ----------------------------
// ES9:命名分组捕获
const t2 = '2019-06-07'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
/*
{
    0, 1 ,2, 3, index, input ,length, // 同上
    groups: {
        { year: "2019", month: "06", day: "07" }
    }
}
*/
 
t2.groups.year // 2019
t2.groups.month // 06
t2.groups.day // 07

后行断言

先行断言:

const test = 'hello world'
test.match(/hello(?=\sworld)/) // hello 后要紧跟 \sworld
// 先行断言:先遇到一个条件,再判断后面的是否满足
 
/*
{
    0: "hello"
    groups: undefined
    index: 0
    input: "hello world"
    length: 1
}
*/

后行断言:

const test = 'hello world'
test.match(/(?<=hello\s)world/) // world 前面是不是 hello\s
// 后行断言:已经“走”过去了,再“退回来”判断
 
/*
{
    0: "world"
    groups: undefined
    index: 6
    input: "hello world"
    length: 1
}
*/
 
// 匹配失败就返回 null
test.match(/(?<=hells\s)world/) // null
 
// 判断不等于
test.match(/(?<!hells\s)world/)