JavaScript 在如今的软件开发中已经占据了重要的一席之地【1】,快速的发展和众多的衍生社区(Node、TypeScript、WebAssembly等等)将 JavaScript 推向了新的高度,也产生了新的复杂度。通过回顾 JavaScript 的演进历史,抓住其发展脉络,更好的把握 JavaScript 趋势。
1995年
当时的浏览器霸主网景公司认识到,死板的浏览器内容已经无法满足用户。为了增加浏览器的动态能力,公司决定在自己的浏览器 Netscape Navigator 中增加脚本语言的能力。网景公司同时采用两种思路来完成这一目标,首先是与 Sun 公司合作,把 Java 语言嵌入到浏览器中;同时还雇用了 Brendan Eich 将 Scheme 语言嵌入到浏览器当中。但是很快网景公司的管理层认为最佳选项是发明一种新的编程语言。为了应对竞争,管理层要求 Brendan Eich 快速实现一个原型先添加到浏览器中(又一个草率却意义重大的决定)【2】。于是,JavaScript的故事开始了。
5月
Brendan Eich 在不同的意见和压力下,仅用了10天时间就交付了这一创造新脚本语言,将其名为 Mocha 并提交给公司。对于创造一种编程语言来说,10天时间实在太短,以至于存在诸多设计缺陷。但这一脚本语言时至今日历经20余年反而愈加繁荣,我想这其实已经证明了JavaScript语言的优点要比缺点要突出得多。JavaScript并非凭空设计,其诸多特性继承自Scheme,而 Scheme 与 Lisp 的一种方言(Lisp语言的衍生版本),不难看出 JavaScript 顽强的生命力其实得益于那源自 Lisp 的坚实的设计思想。
9月
处于市场营销的原因,脚本语言 Mocha 被更名为 LiveScript,以此表示这是一项新发明(Live)的脚本语言(Script),并嵌入到新版 Netscape 浏览器一起发布。
12月
网景与 Sun 达成合作协议,LiveScript(或 Mocha)被更名为 JavaScript,定位是浏览器中小任务的脚本语言,同时大型复杂的富客户端应用通过 Java(Sun公司发明的编程语言)来编写(是的,富客户端概念在1995年就已经形成了)。网景想要借助 Java 语言的名气,以 Java 的小兄弟姿态出现在市场当中。网景与Sun的同盟目的是构筑一个以浏览器为基础,向专业开发者提供Java的能力,同时向非专业开发者(non-developer)提供 JavaScript 的便捷(没错,一开始JavaScript 在大家眼中是“外行”用的工具),网景相信二者的协同效应会带来更大的增长(这背后的主要动力还是来自于商业因素,然后协同效应是否真的产生了1+1>2的效果依然有不同意见)。毕竟微软就是这么做的,在Windows的平台上,C/C++提供了专业的应用开发能力,同时 Visual Basic为非专业开发者提供了便捷的能力。顺便一提,同样是出于商业因素,JavaScript在设计时,被要求语法尽量与 Java 相似。
最终,网景高调的发布了新版本 Netscape ,内置了这个看起来像Java,其实无关的脚本语言,一个新诞生的传奇:JavaScript【3】。
互联网从诞生之初,就是竞争最激烈的战场。网景公司的成功引来了另一家科技巨头的觊觎,微软出手了。1995年微软发布了Windows 95系统,并自带 IE 浏览器,这直接导致了浏览器大战的开始【4】。
1996年
微软曾放低姿态向网景寻求合作,如果网景不推出新的 Netscape Navigator 浏览器,那么微软可以在操作系统的市场上做出一些“让步”。彼时的网景正是市场的宠儿,对微软的提议不屑一顾。面对心高气傲的网景,微软退无可退,浏览器的战争悄然开始,微软迅速投入重金进行并购和研发短短时间变推出了自己的 Internet Explorer 浏览器(简称IE)。在网景推出 JavaScript(当时名为LiveScript)之后,微软反编译了 Netscape Navigator 浏览器,并以此创造了自己的浏览器脚本语言:JScript。为了避免与 Sun 产生 Java 商标问题,微软将自己的脚本与命名为 JScript,虽然源自Netscape,但 JScript 和 JavaScript 之间的差异可远比名字要答多了。导致 JavaScript 与 JScript 之间不兼容的主要原因除了浏览器脚本语言没有统一标准外,还因为微软和网景为了吸引开发者,各自在浏览器中添加自己认为优秀的特性。开发者被迫在自行兼容和抛弃一方之间做出选择,其结果是要么成本增加,要么损失用户。
8月
微软发布了支持 JScript 的 Internet Explorer 3.0 ,这也是微软在浏览器市场上真正崛起的开始。
11月
网景公司将未来押在了互联网,提出以 Java 和 JavaScript 为基石,在互联网(Internet)和内部网(Intranet)中依托 Netscape 浏览器打造一个统一的开发和用户平台【5】(如同技术需要遵循技术规律,市场同样要遵循市场规律,当时并没有完成这一计划的成熟条件,即便是多年以后Chrome浏览器也未能实现这一愿景,技术可以成为改变世界的力量,但驾驭这股力量的一定是商业)。IE 浏览器的增长带来的分裂,已经威胁到了网景的产品规划,作为浏览器核心功能的 JavaScript,它的行业标准成了迫在眉睫的问题。
在IE浏览器的巨大压力下,网景决定将 JavaScript 提交给 ECMA(前身为欧洲计算机制造商协会,后成为ISO标准化组织重要组成部分,专注信息和通信系统标准的建立)进行标准化。为推动这一进程,网景将公开 JavaScript 的实现标准,网景、微软、IBM、苹果、Sun 等行业巨头均派出代表参与标准制定过程(也许是由于Lisp的前车之鉴,大家都不远看到 JavaScript 分裂的情景)。ECMA 为 JavaScript 分配第262号标准,即:ECMA-262。标准的制定工作由 ECMA 的第39号技术委员会负责,即 Technical Committee 39,简称 TC-39。在脚本语言的名称上,由于行业巨头之间存在巨大的商业分歧,最终选择了一个妥协的名字:ECMAScript。至此,浏览器脚本语言标准化的准备工作终于尘埃落定,
1997年
6月
由互联网企业代表提交建议,TC-39 审核并制定相关规范,ECMA以262号新版本方式发布的浏览器脚本语言 ECMAScript 正式亮相,从此任企业都可以参考该标准并发布自己的语言实现【6】。
ECMAScript 作为标准语言规范,开发者和浏览器厂商均将其作为重要参考标准,很大程度上防止了浏览器的分裂,但各家都有自己的 ECMAScript 引擎,尤其是 JavaScript、HTML、CSS 这三者的联系,导致不同的浏览器仍然存在差异。
互联网的日新月异也让 ECMAScript 需要不断更新迭代,在浏览器快速更新的时代中,ECMA-262也就不断更新版本,浏览器发展迟滞的时候,ECMA-262 也相应的沉寂很久。
1998年 6月
ECMAScript 2 发布,简称 ES2。
网景公司开源了 Netscape Navigator 浏览器源码,并创建了 Mozilla 组织。
1999年12月
ECMAScript 3 发布,简称 ES3。
网景公司被AOL收购。
2000年
ECMAScript 4(简称:ES4) 的标准提上了工作日程。但此时在浏览器市场上,微软也已经一家独大,IE的统治地位已不可撼动。垄断地位的形成让微软变得傲慢,既然 IE 的 JScript 已经成了浏览器的事实上的标准,那为什么还要与 ECMA 合作呢?微软终于停止了与 ECMA 的合作,参与者们对 ES4 标准的兴趣也越来小。
2003年
TC-39的工作开始陷入停滞状态。ECMAScript 标准化工作也鲜被提及。
鉴于新版本的 ECMAScript 不能完整发布,TC-39 只发布了一份临时性的改进报告。基于这份报告,Adobe 推出了 ActionScript,微软则推出了 JScript.NET。
2004年
Netscape 重组成为 Mozilla 并发布了 Firefox 浏览器。
2005年
真正的突破,来自于Jesse Garrett 发表的一篇名为 《Ajax: a new approach to Web Application》 的文章,介绍了 JavaScript 中一种革命性的技术方案:Ajax【7】。
Ajax 的出现重新点燃了大家对 ECMAScript 的兴趣。TC-39 恢复工作,时隔几年,一大堆JavaScript的新特性被提交上来。
此时 Adobe 公司基于早期的 ES4 草案实现了自己语言 ActionScript 3,并在 TC-39 会议上积极推动 ES4 。Yahoo 作为新晋的 TC-39 成员,没有赶上 ECMAScript 4 的起草过程,但在审核阶段却起到了决定性作用, Yahoo 派出的参会代表是 Douglas Crockford,他既是一名非常有影响力的意见领袖,同时又坚决反对 ES4 草案。原因是 ES4 对于浏览器脚本语言来说太大、太复杂了,他担心 ES4 的复杂最终会让这门脚本语言失去控制。当 Douglas Crockford 提出反对意见后,TC-39 成员的关系变得微妙,以 Adobe 为首的改革派希望通过 ECMAScript 4 发掘新的市场机会,而以微软为首的保守派则希望保持现状,毕竟微软已经处于市场统治地位,对于变革毫无兴趣。所以当 Douglas Crockford 旗帜鲜明的反对 ECMAScript 4 后,微软也倒戈向了 Douglas Crockford ,会议陷入僵局。
在坚决抵制了 ES4 推到重来的方式后,Crockford 提出以细节优化的方法来改善 ECMAScript ,并开始推动 ES3.1 的草案,其它 TC-39 成员当然不愿放弃 ES4,于是貌合神离的 TC-39 成员们在一个办公室里同时着手 2 套标准的制定:ES3.1 和ES4 (彼时的 ES4 草案已经完成,但仍需时间完善)。
2008年
随着 Eich(JavaScript之父)发出的一封邮件,TC-39 最新的会议决策摘要被传递到所有参与者手中,关键决策包括:
- 放弃ES4,全部成员通力合作,加快 ES 3.1 进度,争取第二年年初实现两个可以互操作的实现
- ES3.1 之后的下一步,是共同合作推出新的语法规范,但在语义和语法上的变化程度上都要比 ES4 更温和。
- ES4 中不适合Web程序开发的提议,将被移除掉,比如:package/namespace/binding。达成一致的关键词是:Harmony(和谐)。
- ES4 中其它提议会被重新措辞并与ES3、ES3.1 尽量兼容,以争取 TC-39 的支持。
ES4 历经8年,最终一地鸡毛。所有支持 ES4 的人都上了生动的一课。此次会议中出现的关键词:Harmony(和谐)也成为了ECMAScript 发展的重要思想。以后各种新提议在未被审核通过前,会先加入到“Harmony”版本提供给关联者使用。
评论:
如果你熟悉 ECMAScript 的 4 和 6 两个版本,就会发现 6 很大程度上是有 4 演变而来,或者说,ES 6 就是当年没能发布出来的 ES 4。现在来看,ES 6 无疑是巨大的成功,但是回到 2005 年,Douglas Crockford 的担忧不无道理,当时的软件条件还不成熟,不具备在浏览器端实施一种高复杂度语言的条件,别忘了 JavaScript 是为了什么目的创建的:浏览器中的小型应用。即使现在,有了像 Node.js、Babel.js、各种网络库的时代,项目的复杂度依然是个难以控制的问题,以至于使用 TypeScript 代替 JavaScript 成为了一种流行方式,我们现在已经能够完全掌控 ECMAScript 了吗?
ECMAScript 4 失败的另一个原因,依然是商业问题。Adobe 力推 ECMAScript 4 背后的动机,是为了扩大 ActionScript 3 的市场份额,彼时的 Adobe 已经通过 Flash 切入到了浏览器的市场,而 Flash 则是用 ActionScript 语言开发。微软会对此坐视不理吗?想想微软与网景之间的较量,微软在1996年就投入10亿美元来对抗网景,后来不惜对 Internet Explorer 浏览器使用“免费”这个终极杀器,将网景彻底挤出市场。说到底,在商业利益微软不会如此好心帮助竞争对手成长。没有微软老大哥的点头,ES4 根本就没有机会得到市场的认可。
2008年
ES4 草案被放弃,TC-39 成员专注于 ES 3.1 工作。
谷歌发布了 Chrome 浏览器。
2009年
ES3.1 完成,并得到 TC-39 全体成员的认可,但是在发布时,遇到名称问题。ES4 虽然从未正式发布,但已经作为 ECMAScript 的一份草案存在多年,此时发布的新版本 ES3.1 编号却比旧的 ES4 低。为了避免名字的混乱,委员会决定将 ES3.1 命名为 ES5 并正式发布。
ES5 是最为成功的一个 ECMAScript 版本,并且得到了主流浏览器的完整支持(实现全部特性)
- Firefox 4 (2011)
- Chrome 19 (2012)
- Safari 6 (2012)
- Opera 12.10 (2012)
- Internet Explorer 10 (2012)
2011年
ECMAScript 5.1 发布,本次标准更新并没有增加任何新特性,而是对 ES5 中有争议的地方进行了明确的解释和定义。因为没有新特性发布,所以此版本仍简称 ES5。
2013年
TC-39 原本计划这一年发布新版本 ECMAScript,代号为 ECMAScript Harmony 代码。但是显然这一版本的野心太大,很难实现,所以 TC-39 决定把它拆成2个部分
- 将优先级高的特性加入新版本
- 其它特性,以后再想办法加入标准当中
为了避免重蹈 ES4 覆辙,ECMAScript 的新版本被命名为: ECMAScript.next。
TC-39 的本意是先发布一个中间版本,然后逐步把 Harmony 版本中的特性添加到 ECMAScript.next 中,完成后再使用正式的新名称。随着新版本的成熟,ECMAScript.next 这个名字也被抛弃,转而直接使用 ECMAScript 6 来称呼这一版本,简称 ES6。
2014年
考虑到要将 Harmony 版本中剩余的特性添加到标准当中,TC-39 决定将 ECMAScript 6 改名为 ECMAScript 2015,简称 ES2015。这是为了给 ECMAScript 快速的版本更新埋下伏笔,以后 TC-39 可以通过年份来区分不同版本的内容。
在改名为 ECMAScript 2015 之前,ES6 的大部分标准已经稳定下来,而这个名字也为大众熟知,并且 ES6 很好的沿袭了 ECMAScript 系列标准的名字,所以习惯上仍用 ES6 来称呼这以版本的 ECMAScript。
2015年
ECMAScript2015 正式发布,简称ES2015,俗称 ES6。
此后,TC-39 兑现了之前的承诺,开始将 Harmony 版本中的特性一点点加入到标准当中。因此,TC-39 每年都会发布新版本的 ECMAScript,但每次的改动都很小。
2016年
ECMAScript 2016 发布,简称 ES2016。
鉴于 ECMAScript 新版本的快速发布模式,TC-39 进行了一次标准采纳方案的修订。每个向 TC-39 提交的提议(proposal)都必须经过4个阶段【8】才能加入到正式标准当中。
- stage-0: 想法
- stage-1: 提议
- stage-2: 惨案
- stage-3: 候选
- stage-4: 完成
当一个提议达到 stage-4 的时候,很大概率会在下一个 ECMAScript 版本当中作为标准发布出去,当然最终决定权在 TC-39。这样做的好处是 ECMAScript 的进度是清晰可见的,而且正式标准是可以预期的。当 stage-4 积累了足够的提议后, TC-39 可以直接将 stage-4 中的提议打包发布成下一版本标准,然后清空 stage-4 等待新提议的进阶。
2017年
ECMAScript 2017 发布,简称 ES2017
2018年
ECMAScript 2018 发布,简称 ES2018
2019年
ECMAScript 2019 发布,简称 ES2019
2020年
ECMAScript 2020 发布,简称 ES2020
尾声
ECMAScript 是一种标准,它有不同的版本:
- ES5
- ES2015(ES6)
... - ES2020
...
各家厂商参考标准实现自己的语言引擎:
- 谷歌,Chrome浏览其的 v8
- Mozilla,Firefox浏览器的 SpiderMonkey
- 苹果,Safari浏览器的 JavaScriptCore
- 微软,IE浏览器的 Chakra
- 微软,Edge浏览器 v8-fork
- Node v8-fork
通过语言引擎支持对应的编程语言,比如:
- JavaScript
- ActionScript
- JScript
JavaScript 是其中最成功的语言,以至于 JavaScript 几乎和 ECMAScript 画上了等号。如今的 JavaScript 已经无处不在,无论它下一步的发展是什么,希望 JavaScript 社区不要忘记 TC-39 的核心精神:Harmony。很多优秀的社区和语言因为分裂、因为不能融入社区导致没落,Lisp、Haskell等等前车之鉴,值得喜爱 JavaScript 的人引以为戒(Rust 似乎也开始出问题)。谦虚、包容是成就一门语言和社区最大的特征。
参考:
【1】https://www.tiobe.com/tiobe-index/javascript/
【2】http://speakingjs.com/es5/ch04.html
【3】https://web.archive.org/web/20080213171613/http://wp.netscape.com/newsref/pr/newsrelease67.html
【4】https://en.wikipedia.org/wiki/Browser_wars#First_Browser_War:_1995-2001
【5】https://web.archive.org/web/19981203070212/http://cgi.netscape.com/newsref/pr/newsrelease289.html
【6】https://www.ecma-international.org/publications/standards/Ecma-262.htm
【7】https://web.archive.org/web/20190226075734/https://adaptivepath.org/ideas/ajax-new-approach-web-applications/
【8】https://tc39.es/process-document/