文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

ES15 (2024)中5个令人惊叹的新JavaScript特性

2024-11-29 20:23

关注

从复杂的异步特性到语法糖数组和现代正则表达式,JavaScript编码现在比以往任何时候都更简单、更快捷。

1.原生数组分组终于到来

Object.groupBy():

const fruits = [
  { name: 'pineapple🍍', color: '🟡' },
  { name: 'apple🍎', color: '🔴' },
  { name: 'banana🍌', color: '🟡' },
  { name: 'strawberry🍓', color: '🔴' },
];

const groupedByColor = Object.groupBy(
  fruits,
  (fruit, index) => fruit.color
);

// 原生 group by 示例
console.log(groupedByColor);

图片

字面意思就是让恐龙级的 Lodash 库失去了最后的存在理由 - 再也不需要了!

图片

我原本期待一个新的实例方法,比如Array.prototype.groupBy,但不知什么原因他们把它做成了静态方法。

然后我们还有Map.groupBy来用对象键进行分组:

const array = [1, 2, 3, 4, 5];

const odd = { odd: true };
const even = { even: true };

Map.groupBy(array, (num, index) => {
  return num % 2 === 0 ? even : odd;
});
// => Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }

不过几乎没人会这样对数组分组,所以可能不会那么受欢迎。

2.从外部解决promise - 现代方式

使用Promise.withResolvers()。

从外部解决promises是很普遍的需求,在此之前我们不得不使用Deferred类来实现:

class Deferred {
  constructor() {
    this.promise = new Promise((resolve, reject) => {
      this.resolve = resolve;
      this.reject = reject;
    });
  }
}

const deferred = new Deferred();

deferred.resolve();

或者从NPM安装 - 又多了一个依赖!

图片

但现在有了ES15的Promise.withResolvers():

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

看看我如何用它来快速地将事件流promise化 - await一个observable:

// data-fetcher.js
const { promise, resolve, reject } = Promise.withResolvers();

function startListening() {
    eventStream.on('data', (data) => {
        resolve(data);
    });
}

async function getData() {
    return await promise;
}

// client.js
const { startListening, getData } = require('./data-fetcher.js');
startListening();

// ✅ 监听单个流事件
const data = await getData();

3. Buffer性能升级

Buffers是用来存储应用程序生成的临时数据的小型数据存储。

它们使得在管道的各个阶段之间传输和处理数据变得非常容易。

像这样的管道:

const fs = require('fs');
const { Transform } = require('stream');

const inputFile = 'input.txt';
const outputFile = 'output.txt';

const inputStream = fs.createReadStream(inputFile, 'utf-8');

const transformStream = new Transform({
    transform(chunk) {
        // ✅ 从缓冲区转换块
    },
});

const outputStream = fs.createWriteStream(outputFile);

// ✅ 开始管道
inputStream.pipe(transformStream).pipe(outputStream);

使用 buffers,每个阶段可以以不同的速度独立处理数据。

但是当通过管道移动的数据超过buffer容量时会发生什么?

以前我们必须将当前所有数据的buffer复制到一个更大的buffer中。

这对性能来说很糟糕,尤其是当管道中将有大量数据时。

ES15为我们提供了解决这个问题的方案:可调整大小的数组buffers。

const resizableBuffer = new ArrayBuffer(1024, {
    maxByteLength: 1024 ** 2,
});

// ✅ 调整大小到 2048 字节
resizableBuffer.resize(1024 * 2);

4.异步升级

Atomics.waitAsync(): ES2024中另一个强大的异步编码特性:

它是当2个代理共享一个buffer时...

代理1"睡眠"并等待代理2完成任务。

当代理2完成时,它使用共享buffer作为通道进行通知。

const sharedBuffer = new SharedArrayBuffer(4096);

const bufferLocation = new Int32Array(sharedBuffer);

// 初始化缓冲区位置的初始值
bufferLocation[37] = 0x1330;

async function doStuff() {
    // ✅ agent 1:在共享缓冲区位置等待直到通知
    Atomics.waitAsync(bufferLocation, 37, 0x1330).then(
        (r) => {  }
    );
}

function asyncTask() {
    // ✅ agent 2:在共享缓冲区位置通知
    const bufferLocation = new Int32Array(sharedBuffer);
    Atomics.notify(bufferLocation, 37);
}

如果你认为这类似于普通的async/await,你绝对是对的。

但最大的区别是:这2个代理可以存在于完全不同的代码上下文中 - 它们只需要访问相同的buffer。

而且:多个代理可以在不同时间访问或等待共享buffer - 其中任何一个都可以通知"唤醒"所有其他代理。

这就像P2P网络;而async/await更像是客户端-服务器请求-响应模式。

const sharedBuffer = new SharedArrayBuffer(4096);

const bufferLocation = new Int32Array(sharedBuffer);

bufferLocation[37] = 0x1330;

// ✅ 从 postMessage() 接收到的共享缓冲区

const code = `
var ia = null;
onmessage = function (ev) {
    if (!ia) {
        postMessage("Aux worker is running");
        ia = new Int32Array(ev.data);
    }
    postMessage("Aux worker is sleeping for a little bit");
    setTimeout(function () { postMessage("Aux worker is waking"); Atomics.notify(ia, 37); }, 1000);
};`;

async function doStuff() {
    // ✅ agent 1:存在于 Worker 上下文中
    const worker = new Worker(
        'data:application/javascript,' + encodeURIComponent(code)
    );
    worker.onmessage = (event) => {
        // 记录事件
    };
    worker.postMessage(sharedBuffer);
    Atomics.waitAsync(bufferLocation, 37, 0x1330).then(
        (r) => {  }
    );
}

function asyncTask() {
    // ✅ agent 2:在共享缓冲区位置通知
    const bufferLocation = new Int32Array(sharedBuffer);
    Atomics.notify(bufferLocation, 37);
}

5.正则表达式v标志和集合操作

这是一个全新的特性,使正则表达式更加清晰和直观。

使用表达式模式查找和操作复杂字符串 - 在集合操作的帮助下:

// A 和 B 是字符类,如 [a-z]

// 差异:匹配 A 但不匹配 B
[A--B]

// 交集:同时匹配 A 和 B
[A&&B]

// 嵌套字符类
[A--[0-9]]

匹配不断增加的Unicode字符集,如:

所以这里我们使用Unicode正则表达式和v标志来匹配所有希腊字母:

const regex = /[\p{Script_Extensinotallow=Greek}&&\p{Letter}]/v;

最后的想法

总的来说,ES15对JavaScript来说是一个重大飞跃,包含了几个对现代开发至关重要的特性。帮助你以更简洁、更富表现力、更清晰的方式编写更干净的代码。

来源:大迁世界内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯