zl程序教程

您现在的位置是:首页 >  前端

当前栏目

【笔记】再学JavaScript ES(6-10)全版本语法——ES9新增

JavaScriptES笔记 版本 10 语法 新增
2023-09-27 14:26:51 时间


一、for await of——异步遍历

1.集合异步遍历

function gen (time) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(time)
    }, time)
  })
}
// 并没有等待异步操作执行完毕就执行下一个并输出了——for of解决不了异步遍历的问题
function test1 () {
  let arr = [gen(300), gen(100), gen(200)]
  for (let item of arr) {
    // 输出时间戳和返回的结果
    console.log(Date.now(), item.then(console.log))
  }
}
test1()
/**
 1591166863344 Promise{<pending>}
 1591166863345 Promise{<pending>}
 1591166863345 Promise{<pending>}
 100
 200
 300
 */

// 这种看似是异步遍历,其实并不理想
async function test2 () {
  let arr = [gen(300), gen(100), gen(200)]
  for (let item of arr) {
    // 输出时间戳和返回的结果
    console.log(Date.now(), await item.then(console.log))
  }
}
test2()

/**
 300
 1591166863346 undefined
 100
 1591166863648 undefined
 200
 1591166863649 undefined
 */

// for await of 才是异步遍历的最佳选择
async function test3 () {
  let arr = [gen(300), gen(100), gen(200)]
  for await (let item of arr) {
    // 输出时间戳和返回的结果
    console.log(Date.now(), item)
  }
}
test3()
/**
 1591166863649 300
 1591166863650 100
 1591166863650 200
 */

2.自定义可遍历数据结构异步遍历

const obj = {
  count: 0,
  gen (time) {
    return new Promise(resolve => {
      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: ''
          })
        }
      }
    }
  }
}

async function test () {
  for await (let item of obj) {
    console.log(Date.now(), item)
  }
}
test()

二、Promise.finally

无论一步执行成功与否,finish都会执行,例如:

  • 无论数据库连接成功与否,最后一步断开连接都要执行
  • 无论操作成功与否,最后都要弹出弹窗来提醒用户
const gen = (time) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (time < 500) {
        resolve(time)
      } else {
        reject(time)
      }
    }, time)
  })
}
gen(Math.random() * 1000)
  .then(value => console.log('resolve', value))
  .catch(err => console.log('reject', err))
  .finally(() => console.log('finish'))

三、Object.rest&spread——对象合并(类浅拷贝)

1.rest

const obj = {
  a: 1,
  b: 2,
  c: 3,
  d: 4
}
const { a, b, ...rest } = obj
console.log(a, b, rest)

与在数组中使用相比,在对象中需要名称对应

2.spread

const obj1 = {
  a: 1,
  b: 2
}
const obj2 = {
  c: 3,
  d: 4
}
const test = {
  ...obj1,
  ...obj2,
  e: 5
}
console.log(test)
// 拷贝验证
obj2.c = 30
console.log(obj2)
console.log(test)

四、RegExp新增

1.dotAll

在正则中点(.)不支持四个字节的utf16字符 和 行终止符(\n、\r)

// s修饰符:用来让点字符识别行终止符
console.log(/foo.bar/.test('foo\nbar')) // false
console.log(/foo.bar/s.test('foo\nbar')) // true
// u修饰符:用来让点字符识别码点大于0xFFFF的 Unicode 字符
console.log(/^.$/.test('𠮷')) // false
console.log(/^.$/u.test('𠮷')) // true
console.log(/^.$/.test('\uD842\uDFB7')) // false
console.log(/^.$/u.test('\uD842\uDFB7')) // true
// 检测dotAll是否开启
const re = /^.$/s
console.log(re.flags, re.dotAll) // s true

拓展:

2.命名分组捕获

const t1 = '2020-06-03'.match(/(\d{4})-(\d{2})-(\d{2})/)
console.log(t1)
// ["2020-06-03", "2020", "06", "03", index: 0, input: "2020-06-03", groups: undefined]
// 分别对应:完整匹配,分组匹配(多个),匹配到的首位索引,完整的输入字符串,groups
console.log(t1[0]) // 完整匹配
console.log(t1[1]) // 分组匹配
console.log(t1[2]) // 分组匹配
console.log(t1[3]) // 分组匹配

// 命名分组捕获
const t2 = '2020-06-03'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
console.log(t2)
console.log(t2.groups.year)
console.log(t2.groups.month)
console.log(t2.groups.day)
console.log(t2.year)
console.log(t2.month)
console.log(t2.day)

之前:
在这里插入图片描述
之后:
在这里插入图片描述

3.后行断言

const str = 'hello world'
// 先行断言:遇到一个条件,就紧接着直接判断后面是否有符合规则
console.log(str.match(/hello(?=\sworld)/)) // ["hello", index: 0, input: "hello world", groups: undefined]
// 后行断言:遇到一个条件,往回找判断前面是否有符合规则
console.log(str.match(/(?<=hello\s)world/)) // ["world", index: 6, input: "hello world", groups: undefined]

还支持不等于判断

后行断言练习题

  • 请把'$foo %foo foo'字符串中前面是$符号的foo替换成bar
console.log('$foo %foo foo'.replace(/(?<=\$?)foo/, 'bar'))
  • 请提取'$1 is worth about ¥7'字符串中的美元数
console.log('$1 is worth about ¥7'.match(/(?<=\$?)\d/)[0])