Video thumbnail

    JavaScript 的真正演进之路:与 Daniel Ehrenberg 一起深入 TC39

    Valuable insights

    1.TC39开放式JavaScript演进: TC39的JavaScript演进过程开放透明,通过分阶段提案和GitHub协作,鼓励社区在早期阶段贡献反馈,确保新特性在广泛共识下标准化。

    2.JavaScript的严格向后兼容性: JavaScript遵循严格的向后兼容性原则,TC39通过实证方法和浏览器分阶段发布来识别和解决潜在的兼容性问题,以确保语言的稳定性。

    3.TC39的多方协作机制: 浏览器厂商、学术界和行业专家在TC39中共同协作,这种多样化视角确保了语言设计严谨且实用,有效解决了过去可能出现的脱节问题。

    4.公司参与TC39的价值: 公司参与TC39可提升自身开发者生产力。例如,Bloomberg通过贡献TS Blank Space和Import Defer等项目,推动内部需求转化为通用标准。

    5.TC39与TypeScript的紧密合作: TC39与TypeScript团队保持紧密合作,共同推动语言特性发展,例如可选链操作符。这种合作模式解决了提案推进中的产品管理障碍。

    6.模块化未来:打包与表达式: 模块声明和模块表达式是JavaScript未来发展的重要方向。它们旨在解决当前模块加载效率问题,并实现原生的JavaScript打包格式,提高开发效率。

    7.Temporal API提升日期处理: Temporal API的开发旨在弥补JavaScript日期时间处理的不足,提供更健壮、更不容易出错的数据类型,满足了复杂应用场景的需求。

    8.信号与观察者的对比与思考: TC39对Signals和Observables等响应式范式进行了深入探讨,致力于提供更符合实际需求的原生响应式方案,避免潜在的误用问题。

    欢迎与TC39内部:JavaScript如何演进

    TC39是一个致力于推动JavaScript语言演进的委员会。其运作过程对外部参与者而言有时显得不够透明,但实际上,TC39通过提前发布会议议程和将提案开发链接到GitHub仓库来促进开放性。开发者可以通过在提案仓库中提交问题和反馈来贡献,确保他们的意见能在会议前被整合。这种开放的协作模式,结合TC39的分阶段流程,确保了JavaScript的持续演进是基于广泛共识和严格测试的。

    JavaScript提案的四阶段流程

    TC39采纳一套严格的四阶段流程来确保新特性在被纳入语言之前经过充分的讨论和测试。这一流程从初始构想到最终标准化,每一步都旨在构建共识并解决潜在问题。在这一过程中,所有利益相关方,包括浏览器厂商、工具开发者和社区成员,都有机会提供反馈,并根据这些反馈对提案进行迭代和完善,以确保其质量和实用性。

    • 第一阶段:提案处于构想阶段,仅作为想法提出,尚未形成具体草案。
    • 第二阶段:委员会同意未来将其纳入,并有具体草案,但仍有细节待完善。
    • 第三阶段:拥有完整的提案细节,委员会已达成一致,但可能需要进行一致性测试和与其他平台集成(如网络设计)。提案的测试套件被上传至 test262 仓库。
    • 第四阶段:当提案在多个实现中(例如,多个浏览器)得到支持并符合测试要求后,它将被纳入JavaScript标准。ECMAScript规范被称为ECMA 262,因此测试套件被称为test 262。

    关于浏览器和标准的可用性,MDN 的基线规范是一个有用的参考。如果一个功能已经在三个浏览器中实现,它便被视为“测试版基线”;经过几年稳定运行后,它将完全成为基线的一部分。

    向TC39提交新想法或反馈

    对于希望提交新提案的人,建议首先在 es.discourse.group 上创建一个讨论主题。通常,更好的做法是参与现有提案的讨论,与志同道合者结盟,共同推进提案的进展。提案的领导者通常会提供任务,因为总是有很多工作需要完成,而时间却有限。有时,提案的进展受阻并非因为反对,而是因为缺乏人手去完成某些方面的工作。

    关于JavaScript的向后兼容性,该语言以其高标准的向后兼容性而闻名,几乎从不破坏现有功能。这在大多数情况下并非问题,因为添加新功能通常不需要破坏兼容性。然而,有时兼容性风险会比较微妙。例如,向Array类添加方法可能会导致现有库出现问题,因为某些库会检查方法是否存在并使用polyfill。这就是为什么Array.prototype.contains后来被重命名为Array.prototype.includes的原因。

    TC39通过实证方法来发现兼容性问题。虽然他们不会针对每个主要库运行测试,但浏览器有分阶段发布的过程(例如Chrome的Canary和Beta版本)来收集反馈。有时问题直到后期才被发现,浏览器通常能够快速推出补丁以修复错误。总的来说,TC39会尽量避免可能导致向后兼容性问题的模式,这通常不会阻碍语言的开发。

    提案的政治与共识建设

    浏览器厂商与TC39的互动至关重要,因为所有JavaScript引擎团队都在TC39中有代表。过去,特别是在ES6(ECMAScript 2015)时期,浏览器代表与实际引擎实现者之间存在脱节,导致一些设计不佳的功能被标准化。然而,现在情况已显著改善,浏览器团队已加强了其代表性,并建立了更好的沟通机制,能够及时收集同事的反馈并带到委员会,从而避免潜在的实现困难。这种改进的工作关系确保了新功能在设计上更加完善和实用。

    TC39委员会的构成

    TC39委员会由来自不同背景的人组成,包括JavaScript开发者、学者、理论家和实现者。这种多样性确保了从多个角度审视语言设计。委员会成员不仅仅是JavaScript代码的编写者,他们还深入参与到语言本身的规范工作中,例如设计语言如何运行。其中不乏专注于形式化方法的行业专业人士,以及维护大型网络产品或工具框架的人员,他们都提供了互补且重要的视角。

    TC39的参与方式与会议

    TC39的大部分工作都在GitHub上进行,任何人都可以参与,无论是否为委员会成员。各种提案都在 TC39/proposals 仓库中列出,每个提案都有自己的仓库,可以提交问题和拉取请求,并讨论用例。委员会每年举行六次会议,其中三次为期三天是线下会议,另外三次是远程会议,所有会议都是混合形式。希望参加会议的人通常需要是受邀专家或成员。

    公司加入ECMA基金会的考量

    许多公司广泛使用JavaScript,并将其视为提高开发者生产力的投资。尽管JavaScript标准库相对较小,缺少其他现代编程语言的许多功能,但通过参与ECMA基金会,公司可以直接投资于改进语言,从而提升自身组织的开发效率。例如,Bloomberg参与其中,旨在通过现代化平台来改进其基于Chromium的Bloomberg Terminal产品的前端开发能力。

    “我们不希望仅仅创造我们自己的‘怪异’事物。我们希望与生态系统保持一致。”

    关于 TS Blank Space 项目,这是Bloomberg的Ashley Claymore创建的一个TypeScript到JavaScript的转译器,它用空格替换所有类型信息。这意味着不需要源映射,因为偏移量完全相同,从而有助于调试并加快编译速度。该项目最初是为内部使用而创建的,但后来已开源。其核心理念是“现代TypeScript”,即仅将TypeScript用于类型检查,而不涉及运行时行为。

    语法创新与生态系统挑战

    TC39和TypeScript团队之间存在密切的合作关系。TypeScript作为JavaScript的一个重要实现,其新变化主要集中在类型空间,而不是添加“现代TypeScript”范畴之外的功能。这种合作模式在许多功能上都非常有效,例如可选链操作符(`?.`)。尽管最初社区抱怨TC39进展缓慢,但TypeScript团队与TC39合作推动了提案的进展,而不是在TypeScript中单独实现。这表明了当缺乏进展时,通常不是因为反对,而是因为缺乏产品管理方面的工作来推动提案并解决分歧。

    关于纯函数与导入延迟

    关于纯函数的提议,特别是为了实现模块的惰性加载而定义纯模块,TC39决定采用“导入延迟”(import-defer)功能,该功能目前处于第三阶段。通过使用 `import-defer star as namespace from 'module'` 语法,模块的顶层语句不会立即执行,直到访问其属性时才会运行。这显著节省了加载时间,并且已在Webpack中实现,Safari的JavaScriptCore中也正在审查中。这一功能由Egalia实施,并得到了TC39的支持。

    信号与类型收窄

    纯函数的另一个维度体现在信号(signals)或React等单向数据流框架中,它们强调将模型计算为视图。在这些框架中,UI通常由路由和缓存查询结果等驱动,理想情况下应通过纯函数实现。虽然“纯”的定义有时微妙,但其核心在于函数在相同输入下总能产生相同输出,并且不会产生不当的外部副作用或隐藏的状态。在TypeScript中,尽管存在类型收窄机制,但它不适用于函数调用,例如在访问信号的.get或.set方法时。TypeScript团队尚未解决这一问题,因为它非常专业,且TypeScript允许自身在某些情况下不健全,以保持进化的灵活性。

    “TypeScript的优点在于它允许自身不健全。它允许自身做出看似实用的决策。”

    Josh Goldberg是TypeScript ESLint的维护者,他作为受邀专家参与TC39,为生态系统提供了宝贵的见解。他曾提议在TypeScript中标记纯函数,以避免在访问信号属性时进行额外的类型检查。

    规范的影响者:Babel、打包器及其他

    工具链如Babel和打包器在JavaScript规范的演进中扮演着重要角色。Nicolo Ribaldo是Babel项目的成员,也是EGALIA的员工,他积极推动工具领域的人员为TC39事务提供输入。这些贡献对于确保语言特性与实际工具使用场景保持一致至关重要。例如,TypeScript的类型收窄功能,即在条件语句中根据类型断言来缩小变量类型,在处理变量和属性时运作良好,但对于函数调用则无效。这是因为TypeScript目前没有专门的机制来识别函数调用的特殊性。

    类型注释提案

    “类型即注释”提案最初旨在将TypeScript语法引入JavaScript,但类型在运行时会被擦除,不具备语义。尽管此提案仍处于第一阶段,其未来发展尚不明确。关键在于标准化一种与TypeScript现有类型语法和语义相符的机制,即使类型语义不共享,也应标准化类型语法以供工具使用。这样可以简化工具链的实现,并确保类型信息可以被忽略或剥离。

    JSDoc与TypeScript语法的对比

    JSDoc作为一种普遍接受的注释方式,其标准化可能有助于相关工具更好地协作。然而,所有JavaScript构建工具都能自动忽略注释,因此从这个角度看,标准化JSDoc并非解决构建问题的关键。此外,JSDoc在使用上不如TypeScript语法便捷,功能也相对受限,尤其是在处理嵌套表达式中的类型时,会显得非常笨拙。相比之下,TypeScript语法设计良好,尽管复杂,但已证明开发者能够很好地驾驭,并提供更好的开发体验。虽然JavaScript允许非常复杂的类型,但TypeScript成功地提供了内聚的表示方式,这在其他语言(如C++模板)中也很常见,能够支持高级的元编程需求。

    特性
    JSDoc
    TypeScript 语法
    人体工程学
    笨拙,尤其在嵌套表达式中
    设计良好,易于管理
    功能限制
    功能受限,如需更多功能需不断添加
    功能强大,支持复杂的类型检查逻辑
    兼容性
    已在各种工具中广泛接受
    生态系统标准,支持高级类型需求
    运行时语义
    运行时被忽略
    运行时被擦除,无语义

    在Bloomberg内部,JavaScript的开发也涉及到许多复杂的类型,以及生成类型声明的构建流程,以使内部API更具人体工程学和真实类型。Daniel Ehrenberg表示,功能开发的过程是案例性的,有时内部的需求会启发通用功能的开发,有时则是现有提案能够很好地满足Bloomberg的需求。

    未来特性:导入延迟、TS差距与模块计划

    JavaScript特性的发展有时源于公司内部的需求,例如Bloomberg的TS Blank Space项目和导入延迟(import defer)。导入延迟(import defer)的引入是为了提升Bloomberg Terminal的启动性能。与其偏离现有生态系统,不如将内部的优化策略推广为标准,因为长期来看,偏离标准会导致高昂的成本。

    Temporal API与日期时间处理

    另一个重要提案是 Temporal API,它旨在解决JavaScript中日期和时间处理的复杂性和潜在错误。由于JavaScript中日期和时间操作的易错性,以及Bloomberg在金融领域对日期时间处理的大量需求,该API预计将大幅减少bug并提高数据类型的可靠性。Mozilla的Andre Bargul已在SpiderMonkey和Firefox中实现该API,并提供了有益的反馈。对于日期和时间、信号这类问题,其解决方案趋于一致,并非短暂的趋势,而是业界经过长期探索形成的共识。

    Observable与Signals的争议

    Observable提案尽管已在第二阶段停留多年,但其与 WICG 提案的冲突以及与Web平台集成的不足曾是其主要障碍。Observable提案在2016年曾被深入讨论,但后来因缺乏推动而停滞。Daniel Ehrenberg曾因其与Web平台集成问题而对其提出质疑,但这些技术问题已得到解决。尽管Observable作为事件流的代表非常出色,但Daniel对其在响应式编程中作为平台推荐方式的地位持怀疑态度,因为它更多地代表了推拉式数据流,而非包含当前值的单元格,这与人们在使用Observable时常寻求的功能存在偏差。

    “我不想让人们将其理解为Web平台推荐的响应式编程方式。它们是一种‘破损’的响应式方式。”

    Daniel Ehrenberg认为,Observable经常被过度使用或误用。它作为一种基础类型,可以实现许多功能,但这并不意味着应该在所有情况下都使用它。Signals在这方面做得更好,它能够更好地表示当前值,并且具有自动追踪和无故障的特性,确保在计算时获得一致的值视图,避免了Observable可能出现的旧新值混杂问题。虽然两者并行发展,但Daniel希望未来的文档能清晰解释它们之间的差异,避免开发者走入歧途。

    社区参与与下一步发展

    WICG(Web Incubator Community Group)并非一个标准委员会,而是一个旨在收集多方兴趣并协作开发想法的平台,它提供知识产权保护。WICG的项目最终需要移交到正式的工作组(如WhatWG,HTML的标准化机构)进行标准化和维护。虽然浏览器可以自由地发布任何功能,不受标准限制,但它们通常依赖于标准世界提供价值,以推动技术发展。尽管人们有时会对标准制定过程的缓慢感到沮丧,并可能选择“捷径”,但TC39致力于确保其工作具有建设性。

    模块声明与模块表达式

    Daniel Ehrenberg最热衷的提案之一是模块声明(module declarations)和模块表达式(module expressions)。这些功能旨在允许在同一个文件中定义多个ES模块。目前,虽然可以使用ES模块来打包整个网站,但打包器通常需要实现一个CommonJS加载器,这可能导致语义上的不一致。如果JavaScript能够完全原生支持ES模块,并引入原生的JavaScript打包格式,将能够解决现有方案的局限性。当前网络上每个模块的导入都会产生单独的网络请求,导致糟糕的“瀑布效应”。

    • 允许在同一文件中包含多个ES模块,解决当前每个模块单独网络请求导致的“瀑布效应”。
    • 支持匿名模块,可作为参数传递给函数,例如启动Worker,从而实现代码的捆绑而无需使用可能受限的数据URL。
    • 引入模块声明,允许将多个模块绑定到特定的变量上,并可在运行时进行导入,包括在静态导入语句中。

    该提案由Niccolo Ribaldo撰写,被认为是实现完整ES模块支持的关键缺失功能,它有助于实现热模块重载等高级功能。TC39内部有一个名为“Harmony工作组”的小组,致力于ES6和模块相关工作,他们有一个Matrix聊天室和定期会议,对所有人开放,欢迎有兴趣的贡献者加入,共同推动这一重要提案的标准化。

    Useful links

    These links were generated based on the content of the video to help you deepen your knowledge about the topics discussed.

    This article was AI generated. It may contain errors and should be verified with the original source.
    VideoToWordsClarifyTube

    © 2025 ClarifyTube. All rights reserved.