Skip to content

ECMAScript 2024(ES15)

Group By

Object.groupBy()

静态方法根据提供的回调函数返回的字符串值对给定可迭代对象中的元素进行分组。返回的对象具有每个组的单独属性,其中包含组中的元素的数组。

js
const inventory = [
  { name: 'asparagus', type: 'vegetables', quantity: 5 },
  { name: 'bananas', type: 'fruit', quantity: 0 },
  { name: 'goat', type: 'meat', quantity: 23 },
  { name: 'cherries', type: 'fruit', quantity: 5 },
  { name: 'fish', type: 'meat', quantity: 22 },
]

// 根据元素的 type 属性的值对元素进行分组
const result = Object.groupBy(inventory, ({ type }) => type)

console.log(result)

/* Result is:
{
  vegetables: [
    { name: 'asparagus', type: 'vegetables', quantity: 5 },
  ],
  fruit: [
    { name: 'bananas', type: 'fruit', quantity: 0 },
    { name: 'cherries', type: 'fruit', quantity: 5 }
  ],
  meat: [
    { name: 'goat', type: 'meat', quantity: 23 },
    { name: 'fish', type: 'meat', quantity: 22 }
  ]
}
*/
js
const inventory = [
  { name: 'asparagus', type: 'vegetables', quantity: 5 },
  { name: 'bananas', type: 'fruit', quantity: 0 },
  { name: 'goat', type: 'meat', quantity: 23 },
  { name: 'cherries', type: 'fruit', quantity: 5 },
  { name: 'fish', type: 'meat', quantity: 22 },
]

// 根据 quantity 字段的值将项目分为不同分组(sufficient/restock)。
function myCallback({ quantity }) {
  return quantity > 5 ? 'sufficient' : 'restock'
}

const result2 = Object.groupBy(inventory, myCallback)

console.log(result)

/* Result is:
{
  restock: [
    { name: 'asparagus', type: 'vegetables', quantity: 5 },
    { name: 'bananas', type: 'fruit', quantity: 0 },
    { name: 'cherries', type: 'fruit', quantity: 5 }
  ],
  sufficient: [
    { name: 'goat', type: 'meat', quantity: 23 },
    { name: 'fish', type: 'meat', quantity: 22 }
  ]
}
*/

Map.groupBy()

Map.groupBy() 静态方法使用提供的回调函数返回的值对给定可迭代对象中的元素进行分组。最终返回的 Map 使用测试函数返回的唯一值作为键,可用于获取每个组中的元素组成的数组。

该方法主要用于对与对象相关的元素进行分组,特别是当该对象可能随时间而变化时。如果对象不变,你可以使用字符串表示它,并使用 Object.groupBy() 分组元素。

js
const inventory = [
  { name: 'asparagus', type: 'vegetables', quantity: 5 },
  { name: 'bananas', type: 'fruit', quantity: 0 },
  { name: 'goat', type: 'meat', quantity: 23 },
  { name: 'cherries', type: 'fruit', quantity: 5 },
  { name: 'fish', type: 'meat', quantity: 22 },
]

const restock = { restock: true }
const sufficient = { restock: false }
const result = Map.groupBy(inventory, ({ quantity }) =>
  quantity < 6 ? restock : sufficient,
)

console.log(result.get(restock))

/* Result is:
[
  { name: 'asparagus', type: 'vegetables', quantity: 5 },
  { name: 'bananas', type: 'fruit', quantity: 0 },
  { name: 'cherries', type: 'fruit', quantity: 5 },
]
*/

console.log(result.get(sufficient))

/* Result is:
[
  { name: 'goat', type: 'meat', quantity: 23 },
  { name: 'fish', type: 'meat', quantity: 22 },
]
*/

Promise.withResolvers()

Promise.withResolvers() 静态方法返回一个对象,其包含一个新的 Promise 对象和两个函数,用于解决或拒绝它,对应于传入给 Promise() 构造函数执行器的两个参数。

ts
const { promise, resolve, reject } = Promise.withResolvers()

RegExp.prototype.unicodeSets

REGEXP 实例的 UnicoDesets 访问者属性返回是否与此正则表达式一起使用V标志。

  • 如果使用 v 标志, RegExp.prototype.unicodeSets 的值为 true ;否则 false
js
// eslint-disable-next-line prefer-regex-literals
const regex1 = new RegExp(/cdcdcd/v)
// eslint-disable-next-line prefer-regex-literals
const regex2 = new RegExp(/cdcdcd/)

console.log(regex1.unicodeSets)
// Expected output: true

console.log(regex2.unicodeSets)
// Expected output: false
js
// eslint-disable-next-line prefer-regex-literals
const regex1 = new RegExp('[\\p{Lowercase}&&\\p{Script=Greek}]')
// eslint-disable-next-line prefer-regex-literals
const regex2 = new RegExp('[\\p{Lowercase}&&\\p{Script=Greek}]', 'v')

console.log(regex1.unicodeSets)
// Expected output: false

console.log(regex2.unicodeSets)
// Expected output: true
js
console.log(/^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+$/u.test('cdhj996@gmail.com')) // true
console.log(/^[a-zA-Z0-9+_.\-]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+$/v.test('cdhj996@gmail.com')) // true

ArrayBuffers

  • 调整大小
js
// 不允许超过预先定义的 maxByteLength, resize 可增大也可以减小
const buffer = new ArrayBuffer(2, { maxByteLength: 32 })

// byteLength 属性是一个访问器属性,它的 set 访问器函数是 undefined,这意味着你只能读取这个属性。
// 该值在数组创建时确定,并且无法修改。
// 如果这个 ArrayBuffer 被分离,则此属性返回 0。
console.log(buffer.byteLength)
// Expected output: 2

console.log(buffer.resize(12))
// Expected output: undefined

console.log(buffer.byteLength)
// Expected output: 12

console.log(buffer.resize(100))
// Uncaught RangeError: ArrayBuffer.prototype.resize: Invalid length parameter
//     at ArrayBuffer.resize (<anonymous>)
//     at <anonymous>:10:20
  • 转移
js
const original = new ArrayBuffer(16)
const transferred = original.transfer()

// detached 属性是一个访问器属性,其 set 访问器函数是 undefined,这意味着你只能读取此属性。
// 该属性的值在创建 ArrayBuffer 时设置为 false。
// 如果 ArrayBuffer 已被传输,则该值将变为 true,这将使该实例从其底层内存中分离。
// 一旦缓冲区被分离,它就不再可用。
console.log(original.detached)
// Expected output: true

console.log(transferred.detached)
// Expected output: false

SharedArrayBuffers

SharedArrayBuffers 可以调整大小,但只能增长而不能缩小。 它们不可转移,因此无法获取 ArrayBuffers 所获取的方法 .transfer() 。

js
const sab = new SharedArrayBuffer(1024)
worker.postMessage(sab)

String

isWellFormed

isWellFormed() 能够测试一个字符串是否是格式正确的 (即不包含单独代理项)

TIP

“单独代理项(lone surrogate)”是指满足以下描述之一的 16 位码元:

  • 它在范围 0xD800 到 0xDBFF 内(含)(即为前导代理),但它是字符串中的最后一个码元,或者下一个码元不是后尾代理。
  • 它在范围 0xDC00 到 0xDFFF 内(含)(即为后尾代理),但它是字符串中的第一个码元,或者前一个码元不是前导代理。
js
const strings = [
  // 单独的前导代理
  'ab\uD800',
  'ab\uD800c',
  // 单独的后尾代理
  '\uDFFFab',
  'c\uDFFFab',
  // 格式正确
  'abc',
  'ab\uD83D\uDE04c',
]

for (const str of strings) {
  console.log(str.isWellFormed())
}

// Logs:
// false
// false
// false
// false
// true
// true

toWellFormed

toWellFormed() 方法返回一个字符串,其中该字符串的所有单独代理项都被替换为 Unicode 替换字符 U+FFFD

js
const strings = [
  // 单独的前导代理
  'ab\uD800',
  'ab\uD800c',
  // 单独的后尾代理
  '\uDFFFab',
  'c\uDFFFab',
  // 格式正确
  'abc',
  'ab\uD83D\uDE04c',
]

for (const str of strings) {
  console.log(str.toWellFormed())
}

// Logs:
// "ab�"
// "ab�c"
// "�ab"
// "c�ab"
// "abc"
// "ab😄c"

Atomics.waitAsync()

Atomics.waitAsync() 静态方法异步等待共享内存的特定位置并返回一个 Promise。

与 Atomics.wait() 不同,waitAsync 是非阻塞的且可用于主线程。

js
const sab = new SharedArrayBuffer(1024)
const int32 = new Int32Array(sab)

// 令一个读取线程休眠并在位置 0 处等待,预期该位置的值为 0。result.value 将是一个 promise。
const result = Atomics.waitAsync(int32, 0, 0, 1000)
// { async: true, value: Promise {<pending>} }

// 在该读取线程或另一个线程中,对内存位置 0 调用以令该 promise 解决为 "ok"。
Atomics.notify(int32, 0)
// { async: true, value: Promise {<fulfilled>: 'ok'} }

// 如果它没有解决为 "ok",则共享内存该位置的值不符合预期(value 将是 "not-equal" 而不是一个 promise)或已经超时(该 promise 将解决为 "time-out")。