大家好,我卡颂。
最近,Typescript v5.0 beta[1]发布,主打特性是「支持Decorators」。
有同学会疑惑,Decorators
不是早就有的特性么?各种框架(比如Nest.js
、Angular
)早就用的飞起,ts
不也早就支持了么?
之所以会有这样的疑惑,简单的说,现阶段大家使用的是老的Decorators
规范,在ts
中使用需要加上--experimentalDecorators flag
。而ts
本次更新支持的是2022年3月新的Decorator
规范。
这背后更本质的原因,涉及到新的JS
语法诞生的过程。今天,我们就以Decorators
为例聊聊一个新的JS
语法是如何诞生的。
所有ES
语法的诞生都由国际标准组织Ecma International[2]下属的TC39
(the 39nth Technical Committee)委员会负责。
这是个会员制的组织,由入会的公司、组织推举的代表组成。这些代表通常是JS
开发者、学者或编程语言领域的专家(比如大家熟悉的「贺老」)。国内的360、阿里、华为、SujiTech都曾参与TC39
。
委员会定期召开会议推进新的ES
语法落地,这套语法落地的流程被称为The TC39 Process[3]。
值得一提的是,这套流程起源于ES2015[4],也就是大名鼎鼎的ES6
。
ES2015
整个版本的落地用了整整6年,包含大量新特性。我想这也是为什么提到ES
新特性,很多同学首先会想到ES2015
(即ES6
)的原因吧。
从ES2017
开始,每年都会发布新的版本,包含那些通过The TC39 Process
但在上个版本没有发布的特性。
整个流程包含5个阶段,阶段0~阶段4。接下来简要介绍下各阶段的目标。
阶段0被称为Strawperson
(稻草人),由TC39
成员发起,通常是提出新想法或是对未纳入正式的提案进行修改。
比如,Decorator提案[5]由「Yehuda Katz」于2014年4月10日提出。
等到这份提案到阶段3,已经2022年3月了,可想而知一个新特性的诞生有多不容易。
阶段1被称为Proposal
(提案),此时该提案已经成为正式提案。该阶段主要提出一些具体的问题和解决方案。此时会选出一名TC39
成员(通常是该提案的发起者)负责推动该提案。
继续以Decorator提案
举例,他在2015年3月24日到达阶段1。
该阶段[6]指明了Decorator
的:
设计目的
适用范围
比如,适用于类本身:
@F("color")
@G
class Foo {
}
适用于类方法:
class Foo {
@F("color")
@G
bar() { }
}
除此之外,还能适用于类的访问器属性(getter、setter)、对象字面量、对象的访问器属性。
在Decorator
进入阶段1的一个月后,Babel
跟进了Decorator
的polyfill
实现。这个版本的polyfill
被称为legacy
。
我们可以在Babel
官网看到,对于Decorator
特性存在5个可选项:
不同版本的可选项对应了Decorator
提案不同阶段的落地时间,由于不同阶段对Decorator
规范提出了修改意见,所以相应的,Babel
插件也就有了不同可选项。
类似的原因,ts
中支持的Decorator
也就有了不同版本,这也是造成我们开篇提到问题的本质原因。
阶段2被称为Draft
(草稿)。在该阶段会用ES
语法尽可能精确地描述提案的语法、语义和API,并提供实验性的实现。
到了该阶段,意味着提案会有很大概率出现在正式版本的ES
中。
Decorator
到达阶段2的时间是2016年7月28日,距离阶段1已经过去一年多时间。
阶段3被称为Candidate
(候选人)。到了该阶段,提案基本已经定型,仅根据外部反馈针对关键问题进行更改。
ts
在最新的v5.0 beta
版本中默认支持的Decorator
就是阶段3。
阶段4被称为Finished
(完成)。该提案会出现在正式的规范文档中,并在下一个版本的ES
中正式支持。
语言特性的推进是个蛮长的过程,最终达成的是多方博弈的结果。对于ES
来说,这些博弈就体现在这4个阶段中。
还是以Decorator
举例,这个特性在oop
框架(比如Angular
、Mobx
)中是很重要的特性。Angular
团队在实现Angular2
时,最初考虑用AtScript
实现。
而最终Angular
用ts
实现,其中很重要的一个原因是 —— ts
团队承诺实现一些AtScript
特性,尤其是Decorator
。
Typescript v5.0 beta: https://devblogs.microsoft.com/typescript/announcing-typescript-5-0-beta/
[2]Ecma International: https://www.ecma-international.org/
[3]The TC39 Process: https://tc39.es/process-document/
[4]ES2015: https://262.ecma-international.org/6.0/
[5]Decorator提案: https://github.com/tc39/notes/blob/main/meetings/2014-04/apr-10.md
[6]该阶段: https://github.com/wycats/javascript-decorators