JavaScript 的演变:2023-2025 年的新特性解析

news2025/7/19 17:50:07

随着Web技术的飞速发展,ECMAScript(简称ES)作为JavaScript的语言标准,也在不断进化。

本文将带你学习 ECMAScript 2023-2025 的新特性。

一、ECMAScript 2023 新特性

1.1 数组的扩展
Array.prototype.findLast()/Array.prototype.findLastIndex()

findLast() 从后向前遍历数组,并返回满足条件的第一个元素的值, 如果没有找到返回 undefined

const list = [1, 2, 3, 4, 5];
console.log(list.findLast(element => element > 3)); // 输出: 5
console.log(list.findLast(element => element > 6)); // undefined

findLastIndex() 从后向前遍历数组,并返回满足条件的第一个元素的索引。若没有找到对应元素,则返回 -1

const list = [1, 2, 3, 4, 5];
console.log(list.findLast(element => element > 3)); // 输出: 4
console.log(list.findLastIndex(element => element > 6)); // -1
Array.prototype.toSorted(compareFn)

返回一个按升序排序的新数组。与 sort 的区别是,sort 会直接修改原数组。

const list = [5, 2, 4, 6, 1];
const arr = list.toSorted();
console.log(arr); // [1, 2, 4, 5, 6]
console.log(list); // [5, 2, 4, 6, 1]
Array.prototype.toReversed()

Array.prototype.reverse() 类似,该数组的元素顺序被反转,但不改变原始数组,而是返回一个新数组。

const list = [1, 2, 3, 4, 5];
const arr = list.toReversed();
console.log(arr); // [5, 4, 3, 2, 1]
console.log(list); // [1, 2, 3, 4, 5]
Array.prototype.toSpliced()

Array.prototype.splice()类似,在给定索引处删除和/或替换了一些元素,但不改变原始数组,返回一个新数组。

语法:

Array.prototype.toSpliced(start, deleteCount, …items)

示例:

const list = [1, 2, 3, 4, 5];
const arr = list.toSpliced(2, 0, 6);
console.log(list); // [1, 2, 3, 4, 5]
console.log(arr); // [1, 2, 6, 3, 4, 5]
Array.prototype.with(index, value)

替换给定参数 index 位置的数组元素,返回新数组,而不改变原始数组。

const list = [1, 2, 3, 4, 5];
const arr = list.with(2, 6);
console.log(list); // [1, 2, 3, 4, 5]
console.log(arr); // [1, 2, 6, 4, 5]
1.2 WeakMap 扩展

WeakMap 支持 Symbol 作为键。

const weak = new WeakMap();
const key = Symbol("ref");
weak.set(key, "ECMAScript");

console.log(weak.get(key)); // ECMAScript
1.3 Hashbang语法

ECMAScript 2023 中引入 Hashbang 语法,允许我们在代码中使用 shebang 表示法 (#!),用于指定执行脚本时使用的解释器路径。

#!/usr/bin/env node

console.log('Hello from Hashbang Grammar!');

#!/usr/bin/env node 告诉操作系统使用哪个解释器来执行该脚本。在这个例子中,它指示使用/usr/bin/env命令来查找并执行node命令。

二、ECMAScript 2024 新特性

2.1 Promise
Promise.withResolvers

Promise.withResolvers() 允许创建一个新的 Promise,并同时获得 resolvereject 函数。

语法如下:

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

返回值:

  • promise:一个新的 Promise 实例。
  • resolve:对应的 resolve 函数。
  • reject:对应的 reject 函数。

需要手动控制Promise状态(如根据异步操作结果)时,可以使用 Promise.withResolvers()

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

setTimeout(() => {
    resolve('成功');
}, 3000);

promise.then(result => console.log(result)); // 输出:成功
2.2 Object.groupBy() / Map.groupBy()

Map.groupBy() 方法允许开发者将可迭代对象分组为一个新的Map,其中 Mapkey 由回调函数提供。

Map.groupBy([0, -5, 3, -4, 8, 9], x => x < 0 ? -1 : 1)

Object.groupBy() 方法则生成一个对象而非Map,其工作原理与 Map.groupBy() 类似,不过返回一个对象。

Object.groupBy([0, -5, 3, -4, 8, 9], x => x < 0 ? -1 : 1) 

2.3 字符串扩展
String.prototype.isWellFormed()

isWellFormed() 让你能够测试一个字符串是否不包含单独代理项。

“单独代理项(lone surrogate)”是指满足以下描述之一的 16 位码元:
它在范围 0xD800 到 0xDBFF 内(含)(即为前导代理),但它是字符串中的最后一个码元,或者下一个码元不是后尾代理。
它在范围 0xDC00 到 0xDFFF 内(含)(即为后尾代理),但它是字符串中的第一个码元,或者前一个码元不是前导代理。

String.prototype.toWellFormed()

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

2.4 正则表达式
v 标志

RegExp 的 v 标志是 u 标志的超集,额外提供了两个功能。

  • 支持根据字符串的 Unicode 属性进行匹配,通过 \p{...} 语法,开发者可以根据字符的 Unicode 属性来构造正则表达式。例如,\p{RGI_Emoji} 用于匹配任何表情符号,而 \p{White_Space} 匹配所有空白字符。
const re = /^\p{RGI_Emoji}$/v;

// 匹配仅包含一个代码点的表情符号:
console.log(re.test('⚽')); // 输出: true ✅

// 匹配由多个代码点组成的表情符号:
console.log(re.test('??‍⚕️')); // 输出: true ✅

在上面的代码中,正则表达式 ^\p{RGI_Emoji}$ 匹配任何单一表情符号,包括复杂的组合表情符号。这种功能使得正则表达式可以更加准确地处理各种 Unicode 字符。

  • 设置符号:允许在字符类之间进行集合操作,这意味着可以使用 && 操作符执行字符类的交集。例如,表达式 [\p{White_Space}&&\p{ASCII}] 匹配既是空白字符又是 ASCII 字符的字符。
const re = /[\p{White_Space}&&\p{ASCII}]/v;

// 匹配常见的换行符:
console.log(re.test('\n')); // 输出: true

// 匹配其他 Unicode 空白字符,例如行分隔符:
console.log(re.test('\u2028')); // 输出: false
  • Unicode 字符类转义:\p{…}、\P{…}
Temporal

Temporal 是一个全局对象,像 Math 一样位于顶级命名空间中,为 ECMAScript 语言带来了现代化的日期、时间接口。

Temporal API 类似 moment 时间库,提供了精确灵活的日期时间操作 API,从而更轻松地处理复杂的日期和时间。

比如加一天:

const date = Temporal.PlainDate.from("2024-08-14");

console.log(date.add({ days: 1 }).toString()); // Output: 2024-08-15

还在提案中

三、ECMAScript 2025 新特性

3.1 模式匹配

模式匹配,一种根据数据结构匹配并执行相应逻辑的机制,一个更强大的 switch 语句替代方案。

const user = { name: 'Jane', age: 25, isAdmin: false };

const status = match(user) {
  case { name, age, isAdmin: true }: return `${name} is an admin`;
  case { age, isAdmin: false }: return `${age}-year-old user`;
  default: return 'Unknown status';
}

还在提案中 - ECMAScript Pattern Matching

3.2 数组与对象的扩展

新增了不可变数据结构 Record(类似对象)和 Tuple(类似数组)。

const record = #{ a: 1, b: 2 }; // Record

// 尝试修改会报错
record.name = "Bob"; // Error: Cannot assign to read-only property

const tuple = #[1, 2, 3];       // Tuple

提供可预测、不可变的数据结构。

应用场景

  • 状态管理(如 Redux)。
  • 数据传递(避免副作用)。
3.3 正则表达式
命名的捕获组

传统正则表达式中,只能使用普通捕获组(用索引访问)。

const matched = '2025-04'.match(/(\d{4})-(\d{2})/)
const [, year, month] = matched;

匹配结果matched是一个数组,数组第一项是正则匹配的完整的字符串,从第二项开始就依次是捕获组的内容,所以year和month分别是数组第二项,和第三项。

在 ECMAScript 2018 的新特性中,我们可以使用 命名捕获组给正则表达式中的捕获组命名,这样可以更容易地通过名称来引用这些捕获组而不是通过索引。

在正则表达式中使用命名捕获组,你可以在圆括号内使用 ?<组名>

const matched = '2025-04'.match(/(?<year>\d{4})-(?<month>\d{2})/)
const {year, month} = matched.groups
正则修饰符

精准控制匹配规则。

在之前,如果希望能够匹配上,也就是忽略大小写,可以这样写:

/hello World/i.test('Hello world')  // true

但如果只需要对部分进行忽略大小写。比如只需 hello 忽略大小写,上面是无法满足的,不过现在可以了,可以这样使用:

/(?i:h)ello World/.test('Hello World')  // true

(?:) 是非捕获分组。

3.4 Promise
Promise.try()

Promise.try() 方法接受一个函数作为参数,这个函数可以是同步的也可以是异步的。如果该函数返回一个值,Promise.try 会返回一个解析为该值的Promise;如果该函数返回一个Promise,Promise.try 会返回该Promise并保持其状态;如果该函数抛出异常,Promise.try 会返回一个拒绝的Promise,并带有该异常作为拒绝原因‌。

语法如下:

Promise.try( callbackfn, ...args )

示例:

function doSomething(action) {
  return Promise.try(action)
    .then((result) => console.log(result))
    .catch((error) => console.error(error))
    .finally(() => console.log("Done"));
}

doSomething(() => "Sync result");

doSomething(() => {
  throw new Error("Sync error");
});

doSomething(async () => "Async result");

doSomething(async () => {
  throw new Error("Async error");
});

输出:

上面的 doSomething 方法,等价于之前的:

async function doSomething(action) {
  try {
    const result = await action();
    console.log(result);
  } catch (error) {
    console.error(error);
  } finally {
    console.log("Done");
  }
}

可在 Can I use 查看支持度。

3.5 集合的扩展
  • intersection(other):求交集,返回一个新集合,新集合的元素既在this集合中,也在other集合中
  • union(other):求并集,返回一个新集合,新集合元素包含this和other中所有的元素
  • difference(other):求差集,返回一个新集合,新集合元素在this集合中,但不在other集合中
  • symmetricDifference(other):求对称差,返回一个新集合,新集合元素只在this集合中或只在other集合
  • isSubsetOf(other):this集合是否为other集合的子集
  • isSupersetOf(other):his集合是否为other集合的父集
  • isDisjointFrom(other):this集合和other集合是否没有共同元素,也就是交集是否为空

可在 Can I use 查看支持度。

3.6 管道操作符

管道操作符 |> 允许将函数的输出直接作为下一个函数的输入,解决嵌套调用导致的代码可读性问题。

const a = 1;

function add(num) {
    return num + 10
}

function substract(num) {
    return num - 1;
}

const b = a |> add |> substract;  // 10

应用场景

  • 数据处理管道(如数据转换)。
  • 函数式编程中的函数组合。

注:该提案在Babel中已实现实验性支持,2025年有望成为标准。

3.7 JSON模块

支持将 JSON 直接作为模块导入,类似于导入 JavaScript 或 CSS 的方式。

import config from './config.json' assert { type: 'json' };

// 动态导入也支持
const loadLocalization = async (locale) => {
  const translations = await import(`./locales/${locale}.json`, { 
    assert: { type: 'json' } 
  });
  return translations.default;
};

注:该提案在Babel中已实现实验性支持,2025年有望成为标准。

参考资料

  • ecma262
  • Union, intersection, difference, and more are coming to JavaScript Sets
  • Temporal

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2338479.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Java · 初窥门径] Java 注释符

&#x1f31f; 想系统化学习 Java 编程&#xff1f;看看这个&#xff1a;[编程基础] Java 学习手册 0x01&#xff1a;Java 注释符简介 在编写程序时&#xff0c;为了使代码易于理解&#xff0c;通常会为代码加一些注释。Java 注释就是用通俗易懂的语言对代码进行描述或解释&a…

Docker环境下SpringBoot程序内存溢出(OOM)问题深度解析与实战调优

文章目录 一、问题背景与现象还原**1. 业务背景****2. 故障特征****3. 核心痛点****4. 解决目标** 二、核心矛盾点分析**1. JVM 与容器内存协同失效****2. 非堆内存泄漏****3. 容器内存分配策略缺陷** 三、系统性解决方案**1. Docker 容器配置**2. JVM参数优化&#xff08;容器…

【计算机网络】网络基础(协议,网络传输流程、Mac/IP地址 、端口号)

目录 1.协议简述2.网络分层结构2.1 软件分层2.2 网络分层为什么&#xff1f; 是什么&#xff1f;OSI七层模型TCP/IP五层&#xff08;或四层&#xff09;结构 3. 网络与操作系统之间的关系4.从语言角度理解协议5.网络如何传输局域网通信&#xff08;同一网段&#xff09; 不同网…

pgsql中使用jsonb的mybatis-plus和jps的配置

在pgsql中使用jsonb类型的数据时&#xff0c;实体对象要对其进行一些相关的配置&#xff0c;而mybatis和jpa中使用各不相同。 在项目中经常会结合 MyBatis-Plus 和 JPA 进行开发&#xff0c;MyBatis_plus对于操作数据更灵活&#xff0c;jpa可以自动建表&#xff0c;两者各取其…

使用MetaGPT 创建智能体(2)多智能体

先给上个文章使用MetaGPT 创建智能体&#xff08;1&#xff09;入门打个补丁&#xff1a; 补丁1&#xff1a; MeteGTP中Role和Action的关联和区别&#xff1f;这是这两天再使用MetaGPT时候心中的疑问&#xff0c;这里做个记录 Role&#xff08;角色&#xff09;和 Action&…

C# 使用.NET内置的 IObservable<T> 和 IObserver<T>-观察者模式

核心概念 IObservable<T> 表示 可观察的数据源&#xff08;如事件流、实时数据&#xff09;。 关键方法&#xff1a;Subscribe(IObserver<T> observer)&#xff0c;用于注册观察者。 IObserver<T> 表示 数据的接收者&#xff0c;响应数据变化。 三个核心…

Redis——网络模型之IO讲解

目录 前言 1.用户空间和内核空间 1.2用户空间和内核空间的切换 1.3切换过程 2.阻塞IO 3.非阻塞IO 4.IO多路复用 4.1.IO多路复用过程 4.2.IO多路复用监听方式 4.3.IO多路复用-select 4.4.IO多路复用-poll 4.5.IO多路复用-epoll 4.6.select poll epoll总结 4.7.IO多…

vue3 传参 传入变量名

背景&#xff1a; 需求是&#xff1a;在vue框架中&#xff0c;接口传参我们需要穿“变量名”&#xff0c;而不是字符串 通俗点说法是&#xff1a;在网络接口请求的时候&#xff0c;要传属性名 效果展示&#xff1a; vue2核心代码&#xff1a; this[_keyParam] vue3核心代码&…

旅游特种兵迪士尼大作战:DeepSeek高精准路径优化

DeepSeek大模型高性能核心技术与多模态融合开发 - 商品搜索 - 京东 随着假期的脚步日渐临近&#xff0c;环球影城等备受瞩目的主题游乐场&#xff0c;已然成为大人与孩子们心中不可或缺的节日狂欢圣地。然而&#xff0c;随之而来的庞大客流&#xff0c;却总让无数游客在欢乐的…

【MySQL】第一弹——MySQL数据库结构与操作

目录 一. 数据库介绍1.1 什么是数据库1.2 为什么要使用数据库1.3 主流数据库1.3.1 关系型数据库1.3.2 非关系型数据库 二. MySQL 的结构2.1 MySQL服务器和客户端2.2 MySQL服务器是如何组织数据的 三. 数据库的操作3.1 创建数据库语法格式示例 3.2 查看数据库语法格式示例 3.3 使…

Spring_MVC 快速入门指南

Spring_MVC 快速入门指南 一、Spring_MVC 简介 1. 什么是 Spring_MVC&#xff1f; Spring_MVC 是 Spring 框架的一个模块&#xff0c;用于构建 Web 应用程序。它基于 MVC&#xff08;Model-View-Controller&#xff09;设计模式&#xff0c;将应用程序分为模型&#xff08;M…

L38.【LeetCode题解】四数之和(双指针思想) 从汇编角度分析报错原因

目录 1.题目 2.分析 去重的代码 错误代码 3.完整代码 提交结果 1.题目 四数之和 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元…

字符串系列一>最长回文子串

目录 题目&#xff1a;解析&#xff1a;代码&#xff1a; 题目&#xff1a; 链接: link 解析&#xff1a; 代码&#xff1a; class Solution {public String longestPalindrome(String s) {char[] ss s.toCharArray();int n ss.length;int begin 0;//返回结果的起始字符串…

双击热备方案及不同方案的需求、方案对比

双击热备方案概述 一般实现双机热备的方案有三种,分别是共享存储双机热备方案、镜像双机热备方案、双机双柜双机热备方案,这三种方案对硬件要求不同,大家可以根据自身的业务应用特性来选择具体的双机热备方案以及对应的ServHA双机热备软件产品。 1、镜像双机热备 1.1镜像…

VSCODE插值表达式失效问题

GET https://cdn.jsdelivr.net/npm/vue2.6.14/dist/vue.js net::ERR_CONNECTION_-CSDN博客 更换正确的vue域名 GET https://cdn.jsdelivr.net/npm/vue2.6.14/dist/vue.js net::ERR_CONNECTION_ <script src"https://unpkg.com/vue2.6.14/dist/vue.js"></sc…

【失败】Gnome将默认终端设置为 Kitty

起因 一会儿gnome-terminal一会儿kitty终端&#xff0c;实在是受不了&#xff0c;决定取缔默认的gnome-terminal。 过程 在 Ubuntu 或 Debian 系统上&#xff1a; 确保 Kitty 已经安装。如果未安装&#xff0c;可以在终端中运行命令sudo apt install kitty -y进行安装。 使用系…

蓝桥杯:连连看

本题大意要我们在一个给定的nxm的矩形数组中找出符合条件的格子 条件如下&#xff1a; 1.数值相同 2.两个横坐标和纵坐标的差值相等&#xff08;由此可得是一个对角线上的格子&#xff09; 那么根据以上条件我们可以用HashMap来解决这个问题&#xff0c;统计对角线上数值相同…

Ext系列⽂件系统

Ext系列⽂件系统 1. 理解硬件1.1 磁盘的物理结构1.2 磁盘的存储结构1.3 磁盘的逻辑结构理解过程实际过程 1.4 CHS&&LBA地址 2. 引入文件系统块分区innode 3. Ext2文件系统3.1 宏观认识3.2 block group3.3 块组内部3.3.1 GDT&#xff08;Group Descriptor Table&#xf…

MTK-Android12 13 屏蔽掉Viewing full screen

去掉ROOM 开机第一次提示全屏弹框 文章目录 需求参考资料修改文件实现方案 解决思路grep 源码查找信息grep 查找 grep -rn "Viewing full screen" 找string 字段grep 查找 grep -rn immersive_cling_title 布局grep 查找 grep -rn layout.immersive_mode_cling 对应的…

GitHub创建远程仓库

使用GitHub创建远程仓库&#xff1a;从零开始实现代码托管与协作 前言 在当今软件开发领域&#xff0c;版本控制系统已成为开发者必备的核心工具。作为分布式版本控制系统的代表&#xff0c;Git凭借其强大的分支管理和高效的协作能力&#xff0c;已成为行业标准。而GitHub作为…