前瞻 - 盘点 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 匹配的工作方式。)即使有重复也是如此,因为在每次迭代开始时,重复部分内的捕获组都会被清除。因此,没有理由写这个。

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

相关推荐
安冬的码畜日常1 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
太阳花ˉ1 小时前
html+css+js实现step进度条效果
javascript·css·html
小白学习日记2 小时前
【复习】HTML常用标签<table>
前端·html
john_hjy2 小时前
11. 异步编程
运维·服务器·javascript
风清扬_jd2 小时前
Chromium 中JavaScript Fetch API接口c++代码实现(二)
javascript·c++·chrome
丁总学Java2 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
It'sMyGo3 小时前
Javascript数组研究09_Array.prototype[Symbol.unscopables]
开发语言·javascript·原型模式
懒羊羊大王呀3 小时前
CSS——属性值计算
前端·css