Skip to content

Latest commit

 

History

History
256 lines (173 loc) · 6.74 KB

ES2021(ES12).md

File metadata and controls

256 lines (173 loc) · 6.74 KB

ES2021(ES12)

ES2021 新增了以下功能:

  • String.prototype.replaceAll()
  • Promise.any()AggregateError
  • 数字分隔符(_
  • 逻辑赋值运算符
  • WeakRefs

String.prototype.replaceAll()

replaceAll() 替换正则表达式或字符串的所有匹配项。

String.prototype.replaceAll(searchValue, replaceValue)

searchValue 可以是一个字符串或正则表达式。

console.log('x'.replace('', '_')) // '_x'
console.log('xxx'.replace(/(?:)/g, '_')) // '_x_x_x_'

console.log('xxx'.replaceAll('', '_')) // '_x_x_x_'

// 不带 /g 的情况下,将报错
console.log('aaa'.replaceAll(/a/, 'x')) // TypeError: String.prototype.replaceAll called with a non-global RegExp argument

console.log('aaa'.replaceAll(/a/g, 'x')) // 'xxx'

在匹配的子字符串之前、内部和之后插入文本:

console.log('a1 a2'.replaceAll(/a/g, "($`|$&|$')")) // '(|a|1 a2)1 (a1 |a|2)2'

插入位置组的捕获:

const regExp = /^([A-Za-z]+): (.*)$/gu

'first: Jane'.replaceAll(regExp, 'KEY: $1, VALUE: $2') // 'KEY: first, VALUE: Jane'
  • .* — 单个字符匹配任意次,即贪婪匹配
  • u — Unicode 模式
  • g — 全局匹配,查找所有的匹配项

插入命名组的捕获:

const regExp = /^(?<key>[A-Za-z]+): (?<value>.*)$/gu

'first: Jane'.replaceAll(regExp, 'KEY: $<key>, VALUE: $<value>') // 'KEY: first, VALUE: Jane'

推荐:JavaScript RegExp 对象 — 正则表达式

Promise.any()AggregateError

Promise.any() 返回一个 Promise,它的解决方式取决于参数 promises(它指的是一个可迭代的 Promises)。

  • 如果第一个 Promise 完成,则使用 Promise resolved
const promises = [
  Promise.reject('ERROR A'),
  Promise.reject('ERROR B'),
  Promise.resolve('result')
]

Promise.any(promises).then(console.log) // 'result'
  • 如果所有的 Promise 都被拒绝,将返回一个包含所有拒绝值的 AggregateError 实例。
const promises = [
  Promise.reject('ERROR A'),
  Promise.reject('ERROR B'),
  Promise.reject('ERROR C')
]

Promise.any(promises).catch((aggregateError) =>
  console.log(aggregateError.errors)
)

// ['ERROR A', 'ERROR B', 'ERROR C']

数字分隔符

为了增加更大数字的可读性,从 ES2021 开始,我们可以在数字中使用下划线(_)作为分隔符。

数字组之间的视觉分离:

console.log(1_234_456_789.01) // 1234456789.01
console.log(1_000_000_000) // 1000000000

const fileSystemPermission = 0b111_111_000 // 504
const bytes = 0b1111_10101011_11110000_00001101 // 262926349
const words = 0xa0_b0_c0 // 10531008

我们还可以在分数和指数中使用分隔符:

0.000_001 // 0.000001
1e10_000 // Infinity

const massOfElectronInKg = 9.109_383_56e-31 // 9.10938356e-31
const trillionInShortScale = 1e1_2 // 1000000000000

分隔符的位置有两种限制:

  • 我们只能在两位数之间加下划线。因此,以下所有数字都是非法的:
3_.141
3._141

1_e12
1e_12

_1464301
1464301_

0_b111111000
0b_111111000
  • 我们不能连续使用多个下划线:
123__456 // 不允许

这些限制背后的动机是保持解析简单并避免奇怪的边缘情况。

以下解析数字的函数不支持分隔符:

  • Number()
  • parseInt()
  • parseFloat()
console.log(Number('123_456')) // NaN
console.log(parseInt('123_456')) // 123
console.log(parseFloat('123_456.123')) // 123

理由是数字分隔符用于代码。其他类型的输入应该以不同的方式处理。

下划线(_)作为 bigint 文本中的分隔符

Bigint 通常用于代表金融技术领域的货币。我们可以在 bigint 类型中使用下划线(_)作为分隔符:

const massOfEarthInKg = 1_000_00n // 100000n

与数字一样,有两个限制:

  • 我们只能在两位数之间加一个下划线。
  • 我们最多可以连续使用一个下划线。

逻辑赋值运算符

||=&&=??=,它们都是二元运算符,增加了赋值功能。

| 赋值运算符 | 相当于 | 仅当 a 是 | | ---------- | -------------- | --------- | --- | --- | -------- | ------- | | a | | = b | a | | (a = b) | false | | a &&= b | a && (a = b) | true | | a ??= b | a ?? (a = b) | null |

逻辑或赋值运算符(||=

对于 ||=,如果左侧为 false,则评估右侧表达式并将其分配给左侧变量。

let x = 0
let y = 1

console.log((x ||= y)) // 1
console.log(x || (x = y)) // 1

const updateID = (user) => {
  if (!user.id) user.id = 1

  // Or
  user.id = user.id || 1

  // 使用逻辑或赋值运算符
  user.id ||= 1
}

逻辑与赋值运算符(&&=

对于 &&=,如果左侧为 true,则评估右侧表达式并将其分配给左侧的变量。

let x = 1
let y = 2

console.log((x &&= y)) // 2
console.log(x && (x = y)) // 2

逻辑空赋值运算符(??=

对于 ??=,如果左侧值为 nullundefined,则评估右侧表达式并将其分配给左侧的变量。

console.log((x ??= y))
console.log(x ?? (x = y))

function setOpts(opts) {
  opts.cat ??= 'meow'
  opts.dog ??= 'bow'
  return opts
}

setOpts({ cat: 'meow' }) // {cat: 'meow', dog: 'bow'}

推荐:JavaScript 运算符总结

WeakRefFinalizationRegistry 对象

WeakRef 是一个帮助您创建对象的弱引用的类,因此它们可以被垃圾收集。而 FinalizationRegistry 对象可以让你在对象被垃圾回收时请求一个回调。

let target = {}
let wr = new WeakRef(target)

// wr 和 target 是不一样的

// 创建新注册表
const registry = new FinalizationRegistry((heldValue) => {
  // ...
})

registry.register(myObject, 'some value', myObject)
// ...过了一段时间,如果你不再关心 myObject
registry.unregister(myObject)

更多资料

New in ECMAScript 2021