Code前端首页关于Code前端联系我们

JavaScript 明年将推出新的时间、日期和设置功能

terry 4个月前 (11-25) 阅读数 234 #Javascript
文章标签 JavaScript

image.png

JavaScript 下一次年度更新中将包含的语言功能将在新年年初决定,其中包括到 2025 年 3 月达到第四阶段里程碑的项目(并且有几个功能已经达到了这个水平)。

还有其他一些项目也有望及时上榜——包括至少一个备受期待的项目,该项目似乎终于进入了正轨。ECMAScript 2024 截止日期后,两个新功能进入了第四阶段:用于处理正则表达式的重复命名捕获组和用于处理集合的方法。

为 JavaScript 效率做好准备

能够 在正则表达式的不同分支中使用相同的名称是一个很小但很有用的功能,它将简化表达式的编写,在编写表达式时,您需要匹配可以用不同方式表达但只能匹配一次的内容(例如年份是 2025 年或日期中的 25 年)。目前,如果您将这两个模式都称为“year”,则会出错,因此您必须想出不同的名称。现在,只要它在表达式的不同分支中,用 | 分隔,您就可以使用相同的名称。

“当浏览器都非常快速地生成这些 [实现] 时,这是一种强有力的支持,这也是我们在推动这些提案时尽可能追求的目标。”
– Rob Palmer,TC39 联合主席

多年来,人们一直在讨论使用 JavaScript 的 Set 类的新方法:这是 JavaScript 落后于许多其他语言(如 Python、Ruby、Swift、Rust 和 C#)的功能,开发人员只能编写自己的集合方法或使用 Core.js 等 polyfill。TC39联合主席Rob Palmer将此描述为“另一个典型案例,自 ES 2015 以来,人们一直在编写自己的三到四行实用函数来处理集合并提供基本的集合操作,这已经是九年前的事了。”

“这项提案之所以花费这么长时间是因为它在语言上开辟了新天地,”参与过多项 TC39 提案的彭博软件工程师Ashley Claymore解释道。

在这些新的设置方法出现之前,JavaScript 没有可以与同一类型的另一个实例组合并返回实例的复杂类型,因此没有新功能如何工作的示例。

“我们花了很多时间讨论什么是集合,”Claymore 说。“如果我有一个集合与另一个集合相交,那么另一个集合会是什么?另一个集合是可迭代的吗?它必须是使用 new Set 创建的实际官方集合实例吗?如果将映射传递给集合方法会发生什么?”

“……实际上,我们花了很多时间讨论什么是集合,现在我们已经找到答案了。”
——彭博软件工程师 Ashley Claymore

以正确的方式解决这些技术问题以避免产生意想不到的后果非常重要。

“每个人都同意这很有用,”他继续说道。“Set 应该做这些事情,这些是我们应该拥有的方法。但实际上,我们花了很多时间讨论什么是集合,现在我们已经找到了答案。”

所有这些讨论确保了听起来像基本功能的东西能够以一种适合语言的方式实现。

集合类似于数组,但每个值都是唯一的,因此您只能添加集合中尚未包含的新值。这意味着您可能有兴趣处理一个集合中存在但不存在于另一个集合中的所有值(差异)、两个集合中的任意一个值(只要它们不在两个集合中)(对称差异)、或仅两个集合中的值(交集),或者各种其他组合。这七种新方法涵盖了开发人员需要对集合执行的标准操作范围:并集、交集、差异、对称差异、isSubsetOf、isSupersetOf、isDisjointFrom。

“我经常使用集合,但你通常不会用到它们而不需要其中的一个或多个,你可能会认为它们应该马上出现在标准库中,但事实并非如此。”
—— Brian Kardell,Igalia 开发者倡导者

“我经常使用集合,但你通常不会用到它们而不需要其中的一个或多个,你会认为它们会立即出现在标准库中,但事实并非如此,”Igalia 开发者倡导者 Brian Kardell告诉 The New Stack 。“作为一名开发人员(和开发者倡导者),我对此感到非常兴奋,因为我知道我会永远使用它们——就像我最喜欢的几个数组方法一样。”

尽管开发人员已经能够通过编写自己的函数在 JavaScript 中做到这一点,但使用语言中的这些函数可以节省时间并有助于保持一致性。

“集合和数组方法很有价值,因为它们被广泛使用,”Kardell 继续说道,“并且你不需要重写它们,也不必担心你的大程序是否最终会有五种相同功能的实现。”

因为达到第四阶段意味着至少有两个主要实现,所以开发人员可以考虑立即使用这两个功能。新的 Set 功能现在已在所有主流浏览器中得到支持:它于 2024 年 6 月在 Firefox 和TypeScript 5.5中发布,使其广泛可用,成为Baseline 2024的一部分,Kardell 将其解释为“当我们发布某些东西的最后实现时”。

Palmer 认为 Set 方法进入基线的速度是ECMAScript 标准化过程旨在实现的从标准到广泛可用性的一个很好的例子:“当浏览器都非常快速地生成这些 [实现] 时,这是一种强有力的支持,这也是我们在推动任何这些提案时尽可能追求的目标。你不希望人们因为它们在一个浏览器中不可用而停止使用它们,尽管显然,总有使用 Babel 或 TypeScript 等编译器的解决方案。”

重复捕获组还不够先进:所有主流桌面浏览器和大多数移动浏览器都支持它(它在三星的移动浏览器中仍处于预览状态),但 Node.js 或 Deno 尚未支持它。

下一阶段:装饰器、JSON 模块和 Promises

其他最有可能在 ECMAScript 2025 中准备好的功能是已经进入第三阶段的提案:装饰器、JSON 模块、Promise.try 和(最后的)Temporal。

装饰器

装饰器通过将现有代码包装在另一段代码中来为其添加额外功能(例如为房间添加窗帘或新油漆以使其更加实用)。这可以简单到只需更改代码的外观以使其更具可读性而无需更改底层代码,也可以通过使其更加模块化来提供更灵活的代码结构化方式。

使用装饰器,您可以将依赖项放在类之外,而不是将处理数据存储和模板的逻辑放在您正在编写的类中,这会使灵活性降低,并且更难在其他项目中重复使用。装饰器允许开发人员为常见任务(如日志记录、动态类型检查和其他安全检查(如验证参数))创建抽象,并在需要时将它们添加到类中。

“我们认为从现有装饰器使用方式过渡到新装饰器非常重要,我们希望实现渐进式采用,并善待现有生态系统:我们不是凭空设计的。”
– Daniel Ehrenberg,Ecma 副总裁

这种模式在 React 和 Angular 等框架中被广泛使用,并且已经在 TypeScript 和 Babel 中得到支持很多年了 —— 尽管与经过多年讨论之后的 ECMAScript 提案的形式并不完全相同(允许装饰器使用私有字段和方法)。

尽管装饰器的更广泛概念已经通过在转译器中的广泛使用得到了广泛的验证,但是在 JavaScript 语言本身中就正确方法达成共识还需要相当长的时间。

“我们对装饰器提案进行了多次迭代,最终我们达成一致,既满足了以前的装饰器所需的用例和过渡路径,又满足了浏览器的可实现性问题,”Ecma 副总裁Daniel Ehrenberg解释道。“我们终于能够对所有这些进行三角测量。这确实意味着存在一些差异,但与此同时,我们确实努力确保过渡顺利进行。”

其中一部分是允许代码使用 TypeScript 实验性装饰器的现有语法或提案的新语法。您必须为各个函数选择其中之一,但他解释说,“在一个特定的导出类声明中,装饰器可以位于导出关键字之前或之后。”这是一件小事,但它避免了开发人员需要重写现有代码。

“我们看到从现有装饰器使用的过渡路径很重要,我们希望实现逐步采用并善待现有的生态系统:我们不是在真空中设计这一点,”Ehrenberg指出。

作为将装饰器引入 JavaScript 的一部分,一些关于将装饰器应用于对象、变量和参数的更雄心勃勃的想法被从提案中删除了 - 但这些仍然是使用相同语法的可能扩展。

JSON 模块

另一个简化是,JSON 模块最初是导入属性提案的一部分,该提案是大型模块和谐计划的一部分,旨在填补JavaScript 中ECMAScript 模块功能的空白。它被移至单独的提案,以避免阻碍更通用的概念,即能够包含处理导入内容的说明以及处理 JSON 文件的具体细节。

导入属性和 JSON 模块的实现都在进行中,并且可能会在今年晚些时候同时进入第四阶段。

能够将 JSON 或 CSS 文件标记为要读取的文本而不是要执行的代码有利于提高安全性,因为这意味着文件不会执行开发人员未预料到的操作。虽然这看起来很简单,但 HTML 和浏览器社区以及 ECMAScript 委员会花了一些时间才找到将其集成到浏览器中的正确语法。Chrome 已经随早期版本的语法(由 Microsoft 贡献)一起提供了该功能,但现在已被删除,导入属性和 JSON 模块的实现正在进行中,并且很可能在今年晚些时候同时进入第四阶段。这并不意味着将提案分开是没有意义的;它允许它们以自己的速度前进,即使看起来它们会同时到达。

Promises.try

另一项已经酝酿一段时间的功能填补了使用承诺的一个小空白。

Promises.try 在六月份已经进入第三阶段,并且已经在多种浏览器中实现。

JavaScript 中的 Promise 以结构化的方式处理异步操作的最终成功或失败:promise 链末尾的 catch 方法应该捕获所有错误,然后方法告诉您的代码如何处理错误。 但是如果你调用一个函数或使用一个接受可能是也可能不是异步的回调的 API,Promise.try会将回调的结果包装在一个 Promise 中,因此如果它抛出一个错误,它将被捕获并变成一个被拒绝的 Promise。 这样,你可以确保你可以在一个 Promise 链中处理同步和异步错误。 这是 Core.js(以及早于 JavaScript 实现的第三方 Promise 库,如Bluebird)中实现的另一个流行功能。

Promises.try 于 6 月进入第三阶段,目前已在多种浏览器中实现(Edge 和 Chrome 中已实现,已添加到 WebKit 中,在当前 Firefox 开发人员版本中已标记,并且可能会包含在 2024 年 11 月或 2025 年 1 月的 Firefox 版本中),以及 Bun 和 Cloudflare Worker 等运行时中。一旦 ECMAScript 委员会同意,这足以进入第四阶段,这应该会顺利赶上 ECMAScript 2025。

是时候进行时间

Temporal(当时的 TC39 编辑Brian Terlson在 2021 年首次进入第三阶段时向我们令人印象深刻地描述为“我们损坏的 Date 对象的替代品”)也将为 ECMAScript 2025 做好准备的可能性越来越大,因为最近在处理阻碍它的问题方面取得了很大进展。

当 JavaScript 于 1995 年创建时,它复制了 Java 的日期对象:一个相当简单的实现,Java 于 1997 年将其替换,但在 JavaScript 中却举步维艰(或者更常见的是被 Moment.js 等库替换)。由于日期、时间、时区和日历的复杂性,用 Temporal 替换它总是会花费大量工作,但相对来说争议也不大。

Temporal 显然很受欢迎:在讨论Interop 2023中将包含哪些内容时,Ehrenberg 告诉我们,“他们做了民意调查,了解开发人员喜欢哪些 API,结果 Temporal 获得了很多选票”。那么,为什么一个受欢迎的提案在五年内一直处于进入 JavaScript 语言的边缘呢?

“…专门针对 Temporal 的规范页面数量与整个 ES6 的数量大致相同。”
– Palmer

该提案一直在等待的事情之一是互联网工程任务组 (IETF) 的工作,该工作旨在标准化用于日历和时区注释的 ISO 字符串格式。由于疫情的影响,这项工作有所推迟,于 2024 年 4 月作为新的 RFC 完成,但即使在完成之前,很明显,这并不是阻碍 Temporal 的唯一因素。

日期和时间是一个庞大而复杂的主题,有着复杂的规则(例如英国历史上缺失的 11 天,或者多伦多曾经有一天是 23 小时 30 分钟)。Temporal 最初是解决这个问题的一个非常全面的方法:它是如此全面,以至于随着各种浏览器开始实现它,很明显,将所有需要的代码放入 JavaScript 引擎需要大量的工作,而且可能需要比目前 Apple Watch 或低端 Android 手机上更多的磁盘和可执行内存空间。

研究如何节省空间是一项艰巨的工作,需要查看 Temporal 中的每个参数和函数,了解它的重要性以及如果没有它会有什么损失,而且无需重新设计已经研究了七年的提案或让开发人员更难学习。

尽管 Temporal 规范中有些地方可以优化,但它的范围也必须缩小——主要是通过删除日历和时区对象,这些对象允许开发人员构建自定义日历和时区。这些是 Web 浏览器实施提案中最复杂的部分,也是他们发现错误最多的地方。

“我们确实希望集中精力确保我们仍然能够满足重要的用例。”
– Ehrenberg

埃伦伯格解释说,从规范中删除这些内容是为了“减少实施和维护负担”。“我们真的想集中精力确保我们仍然能够满足重要的用例。”

“考虑到专门用于 Temporal 的规范页面数量与整个 ES6 的大小大致相同,这才是更合理的规模和范围,”Palmer 表示同意。“它变得非常庞大,我们可能会在以后得到这些东西。”

部分原因是新设备将拥有更多的存储空间和内存,从而为 JavaScript 中的更多函数留出空间。而使用 Temporal 的经验让我们更清楚地了解自定义时区和日历的适用性和不适用性,因此这些的新设计(可能基于jsCalendar,旨在取代无处不在的 iCal 格式)很可能是对原始方法的改进。

与此同时,SpiderMonkey、V8、LibJS、JavaScriptCore 和 Boa 的实现正在取得进展, Fullcalendar也推出了一个polyfill。当其中两个可用时,Temporal 最终可以进入第四阶段并成为 JavaScript 的正式组成部分。幸运的话,这将在 ECMAScript 2025 中实现。

让网络真正国际化

像 Temporal 这样雄心勃勃的提案往往需要这种迭代设计(这对通过委员会领导提案的人来说很难;Temporal 已经有多个“冠军”领导这项工作)。

另一项重大而重要的提案,即通过用 JavaScript 标准取代专有消息格式,使网站和应用更易于本地化为多种语言,也进展缓慢。同样,它所涉及的外部 ICU 标准已经取得了重大进展,但 ECMAScript 委员会仍在讨论该提案在 JavaScript 中的范围,其中一些参与者对进展缓慢感到相当沮丧。

再说一次,这正是开发人员想要的:几乎三分之一的 Web 本地化使用了具有与Intl.MessageFormat提案非常相似的 API 的 polyfill(事实上,它基于 2013 年使用之前的 ICU MessageFormat 的类似提案)。

“……它们 [Intl.MessageFormat 等大型提案] 解决了更棘手的问题,而且它们也是一种真正的公共利益 —— 改进这些东西有助于鼓励我们建立一个更加国际化的网络。”
– Kardell

尽管新的 ICU 工作是对 ECMAScript 提案的回应,但 TC39 委员会希望确保该方法对尚未参与 MessageFormat 2 的组织有用:看起来大约有十几个新组织在生产中使用新语法。彭博社已经在开发原型,但看起来需要更多示例才能使该提案达到我们可以推测它何时会成为语言的一部分的阶段。

但卡德尔认为,即使进展缓慢,这些重大提案仍然令人兴奋。“有些事情更难甚至不可能实现——比如Temporal或Intl.MessageFormat——甚至是模块包/内联模块的想法,这些可能需要极大的复杂性,需要构建步骤,或者有些事情甚至完全不可能通过其他方式实现。我因为其他原因对这些感到兴奋。如果我们能实现它们,那将是巨大的。它们不仅会提高一点性能,还会解决更困难的问题,而且它们也是真正的共同利益——改进这些东西有助于鼓励我们建立一个更加国际化的网络。”

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门