es15版本新特新介绍

本文最后更新于 2025年1月26日 凌晨

前言

ECMA-262是定义ECMAScript语言的标准。每个版本的规范都在其网站上有对应的PDF文件可供下载或在线阅读。本教程内容
来源与该网站与MDN
MDN,ECMA-262

简介

以下内容摘自ECMA-262对es2024(es15)更新内容的简介

ECMAScript 2024, the 15th edition, added facilities for resizing and transferring ArrayBuffers and SharedArrayBuffers; added a new RegExp /v flag for creating RegExps with more advanced features for working with sets of strings;
and introduced the Promise.withResolvers convenience method for constructing Promises, the Object.groupBy and Map.groupBy methods for aggregating data, the Atomics.waitAsync method for asynchronously waiting for a change to shared memory,
and the String.prototype.isWellFormed and String.prototype.toWellFormed methods for checking and ensuring that strings contain only well-formed Unicode.

Object.groupBy 与 Map.groupBy

Object.groupBy

根据提供的回调函数返回的字符串值对给定可迭代对象中的元素进行分组,

语法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 对可迭代对象中的元素进行分组。
*
* @function groupBy
* @param {Iterable} items - 一个将要进行元素分组的可迭代对象,如数组(Array)。
* @param {Function} callbackFn - 一个应用于可迭代对象中每个元素的函数。此函数用于决定每个元素所属的分组,
* 应返回一个可被转换为属性键(通常是字符串或symbol)的值,用来标识元素的分组。
* 回调函数接收以下参数:
* - element: 当前处理的元素。
* - index: 当前元素在可迭代对象中的索引位置。
*
* @returns {Object} - 一个对象,其中键由callbackFn返回的值确定,值为包含相应键的元素组成的数组。
*/
Object.groupBy(items, callbackFn)
使用案例:

案例一:(groupBy根据条件分组)对数据进行过滤分组,常见场景:在一个数组中,需要过滤出我们不需要的数组,一般用数组的filter方法可以搞定,但有时候,我们又需要保留被过滤的部分,
进行分组处理,一般处理用reduce方法 进行遍历分组,Object.groupBy的出现,简化了这一过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 需要提取出偶数与奇数
const array = [1,2,3,4,5,6]
// -----------------filter 实现----------------------------------------
// 提取偶数
const evenNumbers = array.filter(number => number % 2 === 0);
console.log("偶数:", evenNumbers); // 输出: [2, 4, 6]
// 提取奇数
const oddNumbers = array.filter(number => number % 2 !== 0);
console.log("奇数:", oddNumbers); // 输出: [1, 3, 5]

// -----------------reduce 实现----------------------------------------
const { evens, odds } = array.reduce((accumulator, current) => {
if (current % 2 === 0) {
accumulator.evens.push(current);
} else {
accumulator.odds.push(current);
}
return accumulator;
}, { evens: [], odds: [] });

console.log("偶数:", evens); // 输出: [2, 4, 6]
console.log("奇数:", odds); // 输出: [1, 3, 5]

// -----------------groupBy 实现----------------------------------------
const result = Object.groupBy(array,(item)=>{return item % 2 === 0 ? '偶数':'奇数' })
console.log(result) // {"奇数": [1,3,5],"偶数": [2,4,6]}

案例二:(groupBy根据属性的值对元素进行分组)
后端在返回用户数据时 是以单个用户为维度,将用户信息传给前端,前端可以需求 对用户进行分类,例如 根据用户的部门分类,根据用户的 职位分类等,
之前一般按照reduce 可以进行分类,groupBy出现后,分类只需要一行代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const userInfo = [
{name:'张三',department:"法务部",level:"p6"},
{name:'李四',department:"后勤部",level:"p9"},
{name:'王五',department:"人事部",level:"p6"},
{name:'杨果',department:"人事部",level:"p7"}
]
// --------------- rudece方法------------------
const groupByDepartment = userInfo.reduce((accumulator, currentItem) => {
// 如果accumulator中还没有当前项的department作为键,则创建一个新数组
if (!accumulator[currentItem.department]) {
accumulator[currentItem.department] = [];
}
// 将当前项添加到对应部门的数组中
accumulator[currentItem.department].push(currentItem);
return accumulator;
}, {});
// --------------- groupBy方法------------------
Object.groupBy(userInfo,({department})=>department)
// {
// "法务部": [{name:'张三',department:"法务部",level:"p6"}],
// "后勤部": [{name:'李四',department:"后勤部",level:"p9"}],
// "人事部": [
// {name:'王五',department:"人事部",level:"p6"},
// {name:'杨果',department:"人事部",level:"p7"}
// ]
// }

可以看出 使用 groupBy 后,代码非常简洁。

Promise.withResolvers 介绍

简介

其出现的作用与目的: 摘自MDN 描述

使用 Promise.withResolvers() 关键的区别在于resolve与和reject函数现在与 Promise 本身处于同一作用域,而不是在执行器中被创建和一次性使用。
这可能使得一些更高级的用例成为可能,例如在重复事件中重用它们,特别是在处理流和队列时。这通常也意味着相比在执行器内包装大量逻辑,嵌套会更少。

该方法返回一个对象,其中包含一个新的Promise对象与其对应的 resolve与 reject:

1
2
3
4
5
6
7
const {promise,resolve,reject} = Promise.withResolvers()
// Promise.withResolvers() 完全等同于以下代码:
let resolve, reject; // 使resolve, reject与promise处于同一作用域
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});

上面这种将resolve, reject与promise 放置在同一作用域的写法,出现在很多知名js框架/库中,该提案的作者列举了一些例子:

Library Example
React inline example
Vue inline example
Axios inline example
TypeScript utility
Vite inline example
Deno stdlib utility

该方法在实际业务中使用很少,一般用于处理处理流和队列相关。
一下例子是实现一个单元素队列,只允许同时存在一个元素。这个队列是基于Promise设计的,特别适用于那些需要处理单个异步任务排队和传递结果的场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class OneElementQueue {
#promise = null;
#resolve = null;
constructor() {
const { promise, resolve } = Promise.withResolvers();
this.#promise = promise;
this.#resolve = resolve;
}
get() {
return this.#promise;
}
put(value) {
this.#resolve(value);
}
}

{ // Putting before getting
const queue = new OneElementQueue();
queue.put('one');
assert.equal(
await queue.get(),
'one'
);
}
{ // Getting before putting
const queue = new OneElementQueue();
setTimeout(
// Runs after `await` pauses the current execution context
() => queue.put('two'),
0
);
assert.equal(
await queue.get(),
'two'
);
}

深入剖析Promise.withResolver –>译文原文 译文原文


es15版本新特新介绍
https://www.wenhai.life/2024/06/29/24062901/
作者
wen Hai
发布于
2024年6月29日
许可协议