fiuoni
fiuoni
13天前 · 5 人阅读

昨天在浏览 Babel 网站时,看到它的 blog 有一篇新的文章,说 Babel 发布了新的代码支持 class 的私有属性和方法。

这着实让我头脑混乱,到底在哪可以了解到最新的规范?而这些规范又是否被支持?支持到什么程度?完全没有头绪。

自从 ES6 规范发布以来,带来很多新的特性,而我们在消化这些大量的知识时,ES 规范也在不停的调整和增加内容。可是我们没有一个特定的流程和渠道来获取最新的资讯,这反而会越来越落后于前沿技术。

所以在2018年的年末我整理了一下学习 ES 特性的流程和过程中要接触到的名词。

什么是 Ecma ?

在20世纪60随着计算机的普及,不同制造商在使用各自的标准开发软件,这使得为这些不同的设备编写语言更加困难。

为了统一计算机领域的部分标准,欧洲知名的计算机制造商们决定城里一个协会来组建并制定章程和规则,这个协会就是「欧洲计算机制造协会」(European Computer Manufacturers Association) 简称「ECMA」

时间到了1994年,为了体现全球化的进程,该协会改名为「欧洲信息和通信系统标准化协会」(European association for standardizing information and communication systems) 简称 「Ecma International」,虽然名称变化了,但是因为某些历史原因「Ecma」的商标却任然保留了下来沿用至今。

Ecma 的历史

什么是 TC39 ?

「TC39」全称「Technical Committee 39」译为「第39号技术委员会」,是 Ecma 组织架构中的一部分。是负责迭代和发展 ECMAScript 语言规范的委员会,它的成员由各个主流浏览器厂商的代表组成,通常每年召开约 6 次会议来讨论未决提案的进展情况,会议的每一项决议必须得到大部分人的赞同,并且没有人强烈反对才可以通过。

TC39 主要负责:

  1. 维护和更新 ECMAScript 编程语言的标准。
  2. 识别、开发、维护 ECMAScript 的扩展功能库。
  3. 开发测试套件。
  4. 为 ISO/IEC JTC 1 提供标准。
  5. 评估和考虑新添加的技术方案。

TC39 - ECMAScript

TC39 - Royalty Free TG

TC39怎么工作

ECMAScript 从 ES5 版本到 ES6 版本的发布经历了6年的时间,这带来了两个问题:

  1. 即使很早就完成的某项特性,也必须等到整个版本发布才能发布出来。
  2. 有些特性的定制会花费很多时间,那么它在实现前都必须承受很大的压力,因为没有赶上本次发布就必须再等很久,直至下一次发布。

因此 TC39 改变了过去漫长的发布流程,从 ECMAScript 2016 (ES7) 开始,每年发布一个版本,这个版本会包含本年完成的所有功能。

那什么功能算是完成,又有什么功能可以加入议程中呢?

这就需要了解一下 TC39 的工作流程,TC39 会收集各种提案,这些提案来自 TC39 会员或注册为 TC39 撰稿人的非会员。而提案会从 0 阶段(stage 0)开始进入审核流程,它们最终会演变为 ECMAScript 的标准,或者被废弃。后面的章节中会详细介绍。

什么是 ECMAScript ?

ECMAScript 是一种计算机语言的规范,是 Ecma 组织的第 262 号规范(Ecma-262)。现在我们也用 ESx 来指代 ECMAScript x 版本(x 代表6、2016、2017等)。

Javascript 是 ECMAScript 的一个实现。之所以用这么奇怪的方式来描述它,是因为任何人或组织都可以依照规范来实现语言。举例来说,微软也曾经按照 ECMAScript 标准开发出一门语言叫做 JScript,这门语言本用在 IE 浏览器中。

不过在普世语境下 Javascript 和 ECMAScript 两个词已经可互换使用了,而它们也确实有很深的羁绊。

1996年8月,微软模仿 JavaScript 开发了一种相近的语言,取名为JScript(JavaScript 是 网景 的注册商标,微软不能用),首先内置于IE 3.0。网景公司面临丧失浏览器脚本语言的主导权的局面。网景公司决定将 JavaScript 提交给 Ecma,希望 JavaScript 能够成为国际标准,以此抵抗微软。

在提交给 Ecma 之所以不叫 JavaScript,一方面是由于商标的关系,Java 是 Sun 公司的商标,根据一份授权协议,只有网景公司可以合法地使用 JavaScript 这个名字,且 JavaScript 已经被网景公司注册为商标,另一方面也是想体现这门语言的制定者是 Ecma,不是网景,这样有利于保证这门语言的开放性和中立性。

ECMAScript® 2018 Language Specification

JavaScript 语言的历史 - JavaScript 教程 - 网道

What is language and what is dialect for computers?

ECMAScript 版本怎么命名?

1997年 Ecma 发布 「ECMAScript Language Specification, Edition 1」简称「ES1」,随后的每次发布都会在原有版本上加1。

2009年 ES5正式发布,而两年后 ES5.1发布。

又过了6年,一拖再拖的 ES6 才问世。

人们已经察觉到 Javascript 的发展速度要比其规范要快得多,一旦一个想法进入讨论阶段,浏览器就会尝试为这个特性开发原型,而社区也会开始编码实验。所以有人建议未来的版本应该基于年份,比如用 ES2016 来标示在 2016 年结束之前敲定的任何特性规范。

尽管 ES6 被正式更名为 ES2015,但人们还是更多的习惯称其为 ES6。不过从 ES6 以后的规范版本就正式使用年份的命名方式。

额外说一句,还没有正式发布的规范也就是还在定制阶段的特性都被称为 ESNext。

你不知道的JavaScript(下卷) -图书-图灵社区

What is ESNext? Is it same as ECMAScript? - Web, Design, Programming

ECMAScript 的规范更新流程是什么?

之前说到 TC39 会收集各种提案,并让这些提案进入审核流程,一步步推进。整个流程有5个阶段,每个阶段都有一定的准入门槛和评定标准,我们也不需要关心这些标准条目,我们只需要知道一个提案到达的阶段越靠后则它被纳入规范的可能性就越大。

stage-0 - 稻草人(straw-man) 基本没有准入门槛,合规的想法都可以进入这个阶段。

stage-1 - 提案(proposal) 需要确定一个提案推进人。然后概括问题或需求并且形成一个解决方案,列举新提案使用的方法或提供的API。讨论关键算法、概念和语义。

stage-2 - 草案(Draft) 这个阶段需要使用正式的规范语言精确地描述语法和语义

stage-3 - 候选方案(Candidate) 当草案进入这个阶段就需要进一步细化并接收用户的反馈,并描述完所有语义、语法和 API。

stage-4 - 结束(Finished) 当进入这个阶段时,提案会接受测试和验收,通过后就会进入下一个版本 ES 规范的标准之中。

每年7月份,TC39 会正式发布当年的 ES 规范。

The TC39 Process

The TC39 process for ECMAScript features

在哪追踪 ES6 以后的规范变化?

很高兴 ECMAScript 拥抱了 GitHub 社区,通过社区本身的力量来发展自身并回馈于社区。

TC39 on GitHub

TC39 拥有很多仓库:

  • ecma262 仓库主要维护 ECMAScript 规范文档。
  • proposals 仓库主要维护提案的列表及进度。
  • 还有很多测试套件和其他一些规范。

所以回归到章节的问题上来,我们要追踪 ES6 以后的规范变化就需要在 proposals 仓库里找答案。这个仓库包含了 4 大部分,分别是 「stage-0 的提案列表」「stage-1 到 3 的提案列表」「结束(stage-4)的提案列表」「非活跃(inactive)的提案列表」

我们在 结束的提案列表里 能找到所有 ES6 以后添加的特性,下面就列出这些特性以及发布的规范版本: ES2016:

  • Array.prototype.includes
  • 幂操作符

ES2017

  • Object.values / Object.entries
  • 字符串填补
  • Object.getOwnPropertyDescriptors
  • 容许函数参数尾后逗号
  • Async 函数
  • 内存分享和原子操作

ES2018

  • 正则表达式 s 标志
  • 正则表达式中组的命名
  • 对象属性的解构赋值
  • 正则表达式反向断言
  • 正则表达式 Unicode 属性转义
  • Promise.prototype.finally
  • 异步迭代器

在 结束的提案列表里 还包含了一些计划在 2019 年发布的特性,由于其还未正式发布我将其归纳在 ESNext 中就不在此列出了。

Release ES2016 Draft 1 · tc39/ecma262 · GitHub

proposals/finished-proposals.md · tc39/proposals · GitHub

ES 标准与浏览器实现差异

特性的演变迅速也让 JavaScript 开发者遇到了问题,新的特性可以使得编写出更高效健壮的代码,但我们我们的网站却要支持未提供这些新特性的旧版浏览器。在功能特性快速进化的环境下这个问题更加严峻。

上图中绿色的部分就是 ECMAScript 特性和浏览器支持的特性的差异部分,这个差异可以分成两大部分:新的 API新的语法

新的 API 是在原有对象的拓展,比如 Array.includes 就是对数组对象的拓展。它通常是解决一些历史遗留问题或者对常用代码逻辑的封装。

举例来说,Object.is() 是一个用于检查两个值是否严格相等的新接口。=== 在处理 NaN-0 这样的值时会有微妙的歧义,而 Object.is() 就是用来解决这样问题的。

NaN === NaN; // falseObject.is(NaN, NaN) // true复制代码

对于 API 的扩展带来的规范特性和浏览器特性的差异,通常都有一个被称为 polyfill 或者 shim 的模式来抹平。这两个词的意思分别是 腻子 和 垫片,从词义上来说已经能很形象的描述它们的作用。

而 polyfill 可以使用 ES5 的代码来实现这些新 API,就以 Object.is() 来说就可以用以下代码来实现:

if (!Object.is) {
  Object.is = function(x, y) {
    // SameValue algorithmif (x === y) { // Steps 1-5, 7-10// Steps 6.b-6.e: +0 != -0return x !== 0 || 1 / x === 1 / y;
    } else {
      // Step 6.a: NaN == NaNreturn x !== x && y !== y;
    }
  };
}
复制代码

新的语法就比如 let ,是对功能的扩展。想要在旧浏览器中使用不支持的语法就必须要使用「转换+编译」的技术,利用专门的工具把代码转化为等价(或近似)的可以在 ES5 环境下工作的代码。

你不知道的JavaScript(下卷) -图书-图灵社区

ECMAScript Shims · GitHub

在哪里查看 ECMAScript 特性在运行环境中的兼容性?

这里提供一个网站,专门查看兼容性表格。包含浏览器、手机端和服务器端。

ECMAScript 6 compatibility table

什么是 Babel?

Babel 是一个 JavaScript 编译工具,专门用来编译 ECMAScript 6+ 的代码让其兼容就浏览器或运行环境。它可以转换语法、补充 API。

在圣经故事里,Babel 译为「巴别塔」,当时世界只讲同一种语言,人类决定修建一座能够通天的高塔来传播自己的名声。上帝知道了此事,担心人类过于强大,就打乱了人类的语言,让人类不讲同语不齐同心。于是人类便分裂开来,这座塔也不再建造了。

而这个编译器借用 Babel 之名,似乎是想帮助人类统一 Javascript 语言呢(笑。

鉴于它在社区的普及程度很高所以本文不会介绍其具体的使用方式,而是介绍它如何配合 TC39 的工作流程。

如今的 Babel 已经发展到第7个大版本,它提供的子功能的责任划分也越来越清晰,对于开发者来说需要关心两个方面:

  • 把代码编译到什么程度?
  • Babel 对新 ES 特性的支持程度是多少?

通常把代码编译到 ES5 的版本是最安全的,这个版本已经得到绝大多数浏览器的支持,但这会让编译后的代码文件更大。但我们总不能在2030年还这样做,随着旧浏览器逐渐被淘汰,我们也不需要把所有的特性都编译至 ES5 的版本。

Babel 本次更新的第7个版本,引入了 @babel/preset-env 来动态管理编译程度。如果进入这个包而不做任何配置,则会默认把代码编译到 ES5 版本。

重要的是这次 @babel/preset-env 仅包含了对已正式发布的 ES 规范的支持。如果要使用任一 stage-0 到 stage-3 中的特性或者 stage-4 中存在但是当年还未正式发布的特性,就必须安装相应的插件。

如果新特性以API的方式实现,就需要在polyfill中查看,polyfill中包含一个core-js列表专门包含了这些API。

巴别塔 - 维基百科,自由的百科全书

@babel/preset-env · Babel

@babel/Plugins · Babel

GitHub - zloirock/core-js: Standard Library

怎么搭配 TC39 和 Babel 来使用最新特性?

这就是本文的最终总结了,怎样尝试使用一个新的特性。

如果你在别人的代码里或者网络上发现一个你没见过的 JS 代码语法你应该怎么办呢?

首先你应该尝试通过搜索引擎找到这种语法的正式名称。然后你就可以去 TC39 的 github 中找一下,你可以在 ecma-262 正式文档中找(不过这个文档太长了)也可以在 proposals 列表里找一下,别遗漏了 finished proposals 和 inactive proposales 列表,最终你就会找到这个语法的介绍和用例。

接着你会想看一下这个语法在不同环境下的支持程度,所以你需要打开兼容性表格查询页面查找这个语法。

接着你也许会想尝试着编写一个用例并运行一下,那你需要在 Babel 的官网里查一下 plugins 列表里是否支持该语法,如果是新的 API 那就需要在 core-js 列表里找一下。

接着你就可以配置好 Babel 并编写用例,编译成浏览器兼容的代码,在浏览器里运行了。

学习 JS 参考页面总集

TC39 on GitHub - TC39 的 GitHub 帐号

ECMAScript® Language Specification - ECMAScript 最新修订版(当年准备发布的文档)

ECMAScript® Language Specification - ECMAScript 最新正式版(已发布的最新文档)

proposals - 提案列表

ECMAScript 6 compatibility table - 兼容性表格查询页面

@babel/Plugins · Babel - Babel 支持的语法插件列表

GitHub - zloirock/core-js - Babel polyfill 中支持的 API 列表

Exploring JS - 在线学习 JS 的网站作者挺牛的

ES.next News - ES 新闻订阅

写于2019年1月。

罗小黑写写文字

如果喜欢文章 请留下一个赞~ 如果喜欢文章 分享给更多人~

掘金中关注我 在简书中关注我

自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 转载时请保留原文链接 以保证可及时获取对文章的订正和修改

收藏 0
javascript
评论 ( 0 )