【筆記】再學JavaScript ES(6-10)全版本語法——ES9新增


一、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])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章