前瞻 - 盘点 ES2025 已经定稿的语法规范

ECMA 与 JavaScript 有啥关系

首先来说说 ECMA 是一个什么样的组织

ECMA 成立于 1961 年,最初是由欧洲的一些计算机制造商联合发起成立的,旨在促进计算机技术在欧洲的发展和标准化。也就是说 ECMA 的成立就是为了通过制定统一的标准,提高计算机系统的兼容性和互操作性。

其中 ECMA - 262JavaScript 语言的核心规范。 最近十年一般都是每隔一年更新一次规范和语法,所以也就是我们所谓的 es2022、es2023、es2024 等。

除了 ECMAScriptECMA 还制定了其他一些重要标准,如 ECMA - 334(C# 语言规范)ECMA - 335(Common Language Infrastructure,CLI)等。

ECMAScript 最新的语法与草案在哪儿看:

其实很简单, 直接去他们的官网即可 ecma-international.org/publication...

上面图面可以明确看出, 我们最新的 应该是 es2024 , 由 24 年 5 月份定稿

可以看到已经更新到 15 个确定版本。 上面的站点链接可以直接去下载历史版本的所有确认的版本文档。 非常详细。

ECMA - 262 规范与语法的定稿

如何定稿

这个也是我非常想给大家聊一聊的话题。 也就是说, 每年 ECMAScript 的新语法新规范是怎么来的

实际上是每年全世界各地的开发人员, 都可以向 ECMA 组织提供他们的提案, 然后由组织人员来筛选, 经过以下几个阶段, 就可以定稿是否该提案被采用:

阶段名称 描述
Stage 0 Proposals 提案的最初始阶段,只是初步概念,未经过详细设计和论证,可能只是一个简单描述或讨论主题,没有完整提案文档,也未进行技术评估或可行性分析
Stage 1 Proposals 当 Stage 0 的想法得到关注后进入此阶段,提案会被细化,形成相对完整的提案文档,包括新特性的语法示例、语义解释、使用场景、兼容性分析等,但还未经过技术委员会深入评审
Active Proposals 已经通过 Stage 1,进入更深入的讨论和完善过程,在社区和技术委员会中引发积极讨论,不断吸收反馈来完善自身,处于活跃的修改状态
Finished Proposals 完成了所有必要的讨论、修改和验证工作,被认为成熟可纳入标准,通过技术委员会评审且在社区得到广泛认可,等待合适时机纳入语言标准文档
Inactive Proposals 由于各种原因(如技术不可行、与语言方向不符、缺乏社区支持等)没有继续推进,可能被搁置或废弃,不再进行开发和完善,除非有特殊情况

来源请参考:github.com/tc39/ecma26...

最后到了 Finished Proposals 才会认为是成熟可靠的提案, 很大概率会出现在 ES2025 的定稿语法规范里面。

所以此次我们要聊的, 就是 Finished Proposals 已经确定的语法。

ES2025 已经定稿语法有哪些

首先我们知道哪儿去找 ES2025 草案已经定稿的规范

这儿有两个站点推荐:

  1. 最新的草案汇总站点 tc39.es/ecma262/

可以明确看到, 它就是 2025 的草案文档, 最近编辑时间是 2024 年 10 月 4 日。

但是这个文章非常的长, 转为 PDF 有六百多页, 纯英文, 而且有非常多的专业词汇, 以及很多草案汇总, 所以要确定哪些是最终定稿草案还是很麻烦的。

  1. ecma-262 github 官方仓库: github.com/tc39/ecma26...

建议直接访问这个官方仓库, 他对草案的各个阶段进行了分类, 就很容易找到我们想要的定稿提案了。

进去之后, 发现 2025 只有两个语法是明确的定稿提案

定稿语法规范详解

proposal-set-methods

这是一项关于向 JavaScript 内置类添加联合和交集等方法的提议Set

提议

这将添加以下方法:

  • Set.prototype.intersection(other)
  • Set.prototype.union(other)
  • Set.prototype.difference(other)
  • Set.prototype.symmetricDifference(other)
  • Set.prototype.isSubsetOf(other)
  • Set.prototype.isSupersetOf(other)
  • Set.prototype.isDisjointFrom(other)

这些方法都要求它们的参数是一个集合,或者至少在具有数字size属性和方法方面看起来像集合的东西。

  1. Set.prototype.intersection(other)

获取交集, 返回结果为 交集结果

js 复制代码
const set1 = new Set([1, 2]);
const set2 = new Set([2, 3]);
const result = set1.intersection(set2);

console.log('result', result);
// 数据结果为是否拥有交集
  1. Set.prototype.union(other)

获取 set 的并集, 返回为并集结果

js 复制代码
let set1 = new Set( [ 1 ,  2 ] ); 
let set2 = new Set( [ 2 ,  3 ] ); 

const res = set1.union(set2);

console.log(res);
// 输出结果:Set(3) {1, 2, 3}
  1. Set.prototype.difference(other)

前面两个应该是比较好理解的。 但是 差集 就并不是很好理解了。 我们可以看看下面这个图

差集就像 sql 的LEFT JOIN。 本质就是先取 A 的全集, 然后减去 B 中的部分。

代码可以参考:

js 复制代码
const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const onlyFrontEnd = frontEndLanguages.difference(backEndLanguages);

// => Set {"HTML", "CSS"} 

const onlyBackEnd = backEndLanguages.difference(frontEndLanguages);

// => Set {"Python", "Java"}
  1. Set.prototype.symmetricDifference(other)

symmetricDifference 就更加不好理解了,还是给一个图。 本质就是排除 A 和 B 交集的部分。

就像 FULL OUTER JOIN 排除两个表中的任何元素。

语法举例

js 复制代码
const frontEndLanguages = new Set(["JavaScript", "HTML", "CSS"]);

const backEndLanguages = new Set(["Python", "Java", "JavaScript"]);

const onlyFrontEnd = frontEndLanguages.symmetricDifference(backEndLanguages);
// => Set {"HTML", "CSS", "Python", "Java"} 

const onlyBackEnd = backEndLanguages.symmetricDifference(frontEndLanguages);
// => Set {"Python", "Java", "HTML", "CSS"}
  1. Set.prototype.isSubsetOf(other)

这个就比较好理解了。 简而言之, 判断是否 B 是否为 A 的子集。

js 复制代码
const A = new Set(["JavaScript", "HTML", "CSS"]);

const B = new Set(["HTML", "CSS"]);

B.isSubsetOf(A);
// => true

A.isSubsetOf(B);
// => false
  1. Set.prototype.isSupersetOf(other)

如果一个集合中的所有元素都出现在第一个集合中,则第二个集合是另一个集合的超集。这与子集的关系相反。

js 复制代码
const A = new Set(["JavaScript", "HTML", "CSS"]);

const B = new Set(["HTML", "CSS"]);

B.isSupersetOf(A);
// => false

A.isSupersetOf(B);
// => true
  1. Set.prototype.isDisjointFrom(other)

如果一个集合与另一个集合没有共同的元素,那么它们就是不相交的。

js 复制代码
const A = new Set(["JavaScript", "HTML", "CSS"]);

const B = new Set(["JavaScript", "Ruby", "Python"]);

const C = new Set(["Java", "C++", "TypeScript"]);

B.isDisjointFrom(C);
// => true - 没有交集元素

A.isDisjointFrom(B);
// => false - 有交集元素 JavaScript

proposal-duplicate-named-capturing-groups

这个是说的正则语法里面支持「捕获组」

目前,在 JavaScript 中,正则表达式中命名的捕获组必须是唯一的。因此

scss 复制代码
str.match(/(?<year>[0-9]{4})-[0-9]{2}|[0-9]{2}-(?<year>[0-9]{4})/)

是错误,因为您重复使用了year组名。但有时您想匹配可以以多种格式编写的内容(如上所示)。在这种情况下,如果能够使用相同的组名就好了。

所以为了解决上面的问题, 才了有此提案

提议

1. 重复的名称必须有不同的替代方案

目前,此提案仅允许您在名称出现在不同的|替代方案中时重复使用名称,因此单个匹配不可能实际多次使用相同的名称。如果您有在单个替代方案中重复使用名称的用例,请打开问题。请注意,这会使语义变得更加复杂。

2. 反向引用

通过这种改变,可以有一个指向多个不同组的反向引用,例如

xml 复制代码
/(?:(?<a>x)|(?<a>y))\k<a>/

然而,上述限制意味着最多只有一个组可以真正参加比赛。*

因此最多只有一个会真正匹配。该提案表示反向引用指的是实际参与的那个。如果没有匹配,它会无条件匹配而不消耗任何输入(这已经是它的工作原理)。

*从技术上讲,不同的组可以参与重复的不同迭代(+、、等),但已经确定只有最后一次迭代才"计数"以用于反向引用。*``{2}

3. 对象groups

与反向引用一样,比赛结果上对象的相应命名属性groups指的是实际参与比赛的组。

为了属性枚举顺序的目的,这些命名属性按照它们在正则表达式中出现的顺序创建,而不管哪些组实际参与了匹配。

补充:您能以不同的方式「引用一个组吗」?

考虑

css 复制代码
/(?<a>x)|\k<a>/

反向引用永远没有用,因为它引用的组处于不同的替代方案中。因此,它的行为是始终匹配而不消耗任何输入。(这很奇怪,但也是它对\1-style 匹配的工作方式。)即使有重复也是如此,因为在每次迭代开始时,重复部分内的捕获组都会被清除。因此,没有理由写这个。

不幸的是,目前这是合法的。该提案不会改变这一点。

相关推荐
careybobo1 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
TDengine (老段)2 小时前
TDengine 中的关联查询
大数据·javascript·网络·物联网·时序数据库·tdengine·iotdb
杉之3 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端3 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡3 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木4 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!4 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
難釋懷5 小时前
JavaScript基础-移动端常见特效
开发语言·前端·javascript
还是鼠鼠5 小时前
Node.js全局生效的中间件
javascript·vscode·中间件·node.js·json·express
自动花钱机5 小时前
WebUI问题总结
前端·javascript·bootstrap·css3·html5