笔记:JavaScript 的二十年

最近看到一个讲述 JS 历史的翻译项目,挺有意思的,打算边读边对其中的内容写一些自己的读后感,深入了解一下 JS 的历史

项目地址:

JavaScript 二十年

网页浏览:

JavaScript 二十年


目录


语言诞生

史前时代

史前时代主要讲述了 1994-1995 年间,JS 之父 Brendan Eich 在十天的期限内完成了 JS 的故事,Eich 在网景工作之前就一直从事语言开发的相关工作,所以才使得这样的英雄壮举得以实现。

还有一些很关键的内容,首先 JS 是一个时势造英雄的产物,网景和 Sun 达成了合作共同抵制微软,所以需要开发一款独立的”脚本语言”,同时出于公司高管的商业要求,这个东西要“像” Java,但是又不能撼动 Java 的地位,于是产生了一些奇怪的设计,而 eval 和 with 这两个备受诟病的设计也是这时候弄进来的。

JS 最开始的设计就是基于对象的,没有基于类主要是出于成本和防止和 Java 直接竞争的原因,JS 开发之初本是希望作为类似 Java 的一个脚本语言,不过后面渐行渐远了。

除此之外——

在盖茨的直接领导下,微软已经迅速意识到它们即将推出的封闭生态信息应用 Blackbird 项目 [Anderson 2007],在跨平台 Web 的兴起之下将无足轻重。因此,盖茨的「互联网浪潮」备忘录 [Gates 1995] 将微软的战略从 Blackbird 重新引导到了 Internet Explorer 与一整套服务器产品上,以应对 Netscape 的攻城略地。

盖茨本来是想在浏览器上搞垄断的,只不过迫于形式才屈从于“跨平台”,我大胆猜测也是出于这样的商业考量微软最终放弃了浏览器团队,最终导致 Chrome 的崛起。

早期版本

这一部分的内容大致介绍了一下初代版本的 JS,这个版本其实已经相对完善了,大部分基础的操作都是借鉴自 C 语言,有一些奇怪的特性来自 Java,还有一些东西来自其他的语言。

总体而言,Eich 高超的水平保证了这个语言的起点很高,但是脚本语言的定位和所谓为了”易用性“的定位使得语言的严谨性被破坏,同时仓促的开发页遗留了很多 bug,Eich 和网景可能在开发之初也没有想到 JS 后面的成功,否则可能投入更多的资源来开发。

诞生花絮

后面简要介绍了一些早期的花絮内容。

首先让我感兴趣的还是微软对于 JS 的态度,由于 Eich 的个人能力突出,使得网景早一步将脚本语言应用在浏览器上成为现实,而微软反应过来为时已晚,不得不兼容 JS 抢占市场份额,时隔这么多年,我们依然可以从文字中领略到硝烟弥漫的商业竞争。

IE 团队非常重视与 Netscape 的竞争。他们希望当时作为 Active Scripting 一部分的脚本调试器能够吸引到 JavaScript Web 开发者使用 IE,因为 Netscape 没有 JavaScript 调试器。但他们也了解到,与 Netscape 浏览器的网站互操作性对于推广 IE 至关重要。于是 Shon Katzenberger 和其他人针对数千个使用 JavaScript 的网站运行了 IE 3 的开发版本,并将结果同 Netscape 2 与 Netscape 3 做了比较。每当发现差异时,Katzenberger 都必须对 Netscape JavaScript 的行为做逆向工程,以了解其不同之处。其中有些行为让他们非常吃惊。当他们发现在 Netscape 的实现中 HTML 页框竟然共享一个公共的对象地址空间并可以自由交换对象时,更是尤其让他们震惊。IE 已将页框实现为隔离的环境,因此需要大量的重新设计才能使对象在其中传递。

除此之外,Eich 真的就是永远的神,领略一下神的风采:

在 1995 年全年和 1996 年的大部分时间里,Brendan Eich 都是唯一全职从事 JavaScript 引擎开发工作的 Netscape 开发者。在 1996 年 8 月发布的 Netscape 3.0 版本中,JavaScript 1.1 仍然主要包含 1995 年 5 月的 10 天原型代码。在发布这个版本后,Eich 认为是时候偿还引擎的技术债,并努力使 JavaScript「成为一门更干净的语言」了。但 Netscape 管理层则希望他研究语言规范。他们对微软针对 JavaScript 规范缺失的批评很敏感,并认为即将开始的语言标准化进程需要这样一份规范作为输入。Eich 拒绝了,他想把重新实现 Mocha 作为开始。要想编写规范,他需要的是仔细检查 Mocha 的实现。他认为在检查 Mocha 时重写 Mocha 是最有效率的方法,这也能让他在初始的设计错误被纳入规范前纠正它们。

由于对辩论感到沮丧,Brendan Eich 离开办公室,在家工作了两个星期。在此期间,他重新设计实现了 JavaScript 引擎的核心。此举的收获是一个更快、更可靠和更灵活的运行引擎。他舍弃了将 JavaScript 值表示为差异联合体的实践,改为使用包含即时原始值的标记指针(tagged pointer)。他还实现了诸如嵌套函数、函数表达式和 switch 语句之类的特性,这些特性从未在原始引擎中实现过。基于引用计数的内存管理器也被替换成了基于标记 / 清除算法的垃圾收集器。


创立标准

JavaScript 的标准化也是网景和甲骨文出于对抗微软的商业化目的促成的,而且这整个过程看起来也非常有趣。

Netscape 的标准专家 Carl Cargill 认识 Ecma 国际组织(Ecma International)的秘书长 Jan van den Beld,并朝这个方向推动了 JavaScript 的标准化。Ecma 对自己的定位是以业务为中心的标准组织,旨在将官僚主义流程最小化,从而把标准制定时间减至最少。由于国际标准组织(ISO)认可 Ecma 国际,Ecma 的标准可以通过快速通道来成为 ISO 标准。除了 Cargill 的人脉以外,Sun 也已经是 Ecma 的会员。

后面就详细记录了 JavaScript 的初版标准的形成过程,大致就是网景、甲骨文、微软和 Ecma 四家的专家相互协作博弈的过程。

关于 JavaScript 的名字由来,有一段比较有趣的描述:

自标准化过程开始起,语言命名上的隐患就已经埋下了。Netscape 起的最初名称「LiveScript」基于它和 Sun 的战略合作伙伴关系而替换成了「JavaScript」。Sun 将「JavaScript」注册成了商标,并将其许可给了 Netscape。尽管 Sun 支持 Netscape 脚本语言的标准化工作,但他们也积极保护与 Java 有关的商标。Sun 似乎不太可能将对「JavaScript」商标的控制权交给标准组织。

Sun 确认了不会将「JavaScript」许可给 Ecma,而 Netscape 则表示对于使用 LiveScript 作为标准名称,没有法律上的异议 … 但在收到 Netscape 的书面确认前,ECMAScript 仍将在规范草案中使用 … Brendan Eich 后来表达了他对命名问题的看法:「ECMAScript 一直是个没人要的商品名,听起来像是种皮肤病。」

最后介绍了一下早期的三个标准的起草过程。

最后的花絮里面讲了一个浏览器博弈论很有意思:

破坏性变更(甚至 bug 修复)可能赶走用户。

新浏览器必须遵从于现有的浏览器。

如果仅在一个浏览器中进行创新,那将是浪费。

第一个吃螃蟹的浏览器,可能反而会丢失市场份额。


改革失败

对 ES4 的第一轮尝试

随着 JavaScript 的影响力不断扩大,越来越多的互联网公司参与到使用和推进 JavaScript 规范的过程中来,同时,大家都希望赋予它更多的功能和特性,已经和 Sun 和网景最初的预设的“一个用在浏览器中简单的脚本语言”的定位产生了冲突,JavaScrip 的改进思想越来越多的向 Java 靠拢,但由于之前 Sun 为了防止 JavaScript 与 Java 产生直接竞争采用了很多奇怪的设计,因此推进规范的过程困难重重。

JavaScript 2.0 并未尝试与原始 JavaScript(甚至还有尚未完成的 ECMAScript 3)完全向后兼容。在向 TC39 介绍 JavaScript 2.0 时,Waldemar Horwat 表示:「至少,你应该能写出在 ECMAScript 1.0 和 2.0(ES4)中都能工作的代码。完全向后兼容会非常痛苦 。」例如可选类型注解所带来的语法复杂性,会导致难以在换行符上支持自动分号插入。Horwat 对向后兼容性的解决方案是在实现中提供多个编译器。他认为根据语言版本切换编译器,要比使用具有严格前向兼容性的单一语言更可取。

但即使是这样,对于初版的 ES4 还是有着很宏伟的目标:

ECMAScript 2.0 是一个进取且大幅改进的 ECMAScript 语言规范,委员会希望在 2000 年实现标准化(当然这个野心可能过大)。ECMAScript 2.0 的主要目标是为「大规模编程」提供支持——这也就是说,要支持开发由多人构建的程序,并可能是史上第一次要在用户的桌面上组装出这些程序。

但就在这个阶段微软开发出了.NET 平台,并且对类 JavaScript 语言提供了支持,同时,网景公司与微软在浏览器领域的竞争也节节败退,到 2000 年,微软的 IE 浏览器已经占据了九成左右的市场份额,微软这时候又重操起了老本行,希望使用一套专有的技术来代替开放的 Web 技术。(ps.微软是真的狡猾,Java 有 JVM,它就整一个.NET;系统也是人家有一个 Linux,它整一个 Windows;前两天偶然知道 mac 上原来很多功能键上都有苹果的图标,后来乔布斯觉得这设计不好看去掉了,看看键盘上的 Windows 图标的我又陷入了沉思。)

微软凭借 IE 在竞争中取胜,并最终获得了 90% 以上的市场份额。它对继续增强自己没有专有控制权的 Web 编程平台的兴趣不大。在微软内部,研发资源从增强开放的浏览器技术(例如 ECMAScript)转到了开发专有的微软技术(如 Windows Presentation Framework)上,微软希望它们能最终淘汰和取代开放的 Web 技术。在 .NET 的编程语言领域,微软专注于 C# 和 VisualBasic .NET。在这种情况下 JScript .NET 的重要性,仅仅取决于它能使多少 JavaScript 程序员迁移到 .NET 平台。

对 ES4 的第二轮尝试

随着浏览器的广泛应用,业界对于在浏览器中运行 Web 应用的需求越来越强烈,但此时浏览器标准并不支持交互足够丰富的应用,微软和 Adobe 都在开发支持对应技术的专有技术栈,开放的 Web 技术栈岌岌可危。就在这个千钧一发的时刻,Brendan Eich 站了出来。(ps.又是这个男人!)

Eich 牵线希望重启 ES4 项目,并且拉来了 Adobe 的一些专家一起帮忙解决 Web 应用的一些问题,但是微软内部有些人意识到 ES4 如果形成一个颠覆性的标准,那么对于微软来说将是十分不利的,于是微软提出 ES4 的方案并不成熟,当前的任务应该是基于 ES3 做一些改进性的工作,就这样 ES4 和 ES3.1 两个项目吵得不可开交。

最终,Adobe 退出了 ES4 项目,ES4 项目也以失败而告终,但是微软也没有获得想象中的胜利:

Allen Wirfs-Brock 回忆说,当 Adobe 宣布退出新版 ES4 时,他感到松了一口气。他知道,微软负责 IE 浏览器的高管们已经意识到,放弃对 IE 浏览器的投资是个战略错误。当时 IE 的市场份额正大量流失到 Firefox 浏览器,而且高管们也知道谷歌正准备推出新的浏览器。微软正在主动面对 Web 开发者中所流传的「微软反对 Web 技术进步」的观点。微软对新版 ES4 的反对(特别是经由 Brendan Eich 和微软 Chris Wilson 的公开争论所暴露出的事实)也更加印证了这种观点。到 2008 年 6 月,Wirfs-Brock 担心微软可能会因为纯粹的商业原因而改变决定:与其公开反对,不如顺其自然地支持新版 ES4。


继往开来

在 ES4 失败之后,ES3.1 还在继续被一些人推进,这次他们采用了一种与之前工作方式不同的工作方式:

人们一致认为,ES3.1 的首要原则是「不要破坏 Web」,亦即确定出有哪些语言变更会改变现有「已与主流浏览器相兼容的」网页的行为。但是现存的网页已有数以亿计,它们实际上依赖了 ECMAScript 规范中的哪些部分呢?对规范的哪些改动会破坏 Web 呢?有一则来自浏览器实现者的趣闻,认为由于现有网页的庞大基数,任何兼容的浏览器特性(不论用法多晦涩或令人难以置信)都可能被某些现存的页面使用。基于这种观点,在所有四种主流浏览器中共通的特性不应被更改,而四种浏览器中有三种支持的特性则很有望被标准化。但对于那些四种浏览器中只有两种支持,或在所有浏览器中都不同的特性和行为,又该怎么办呢?显然,这类特性和行为对于现有的可交互 Web 并非必需,并且还可能会在标准化过程中被进一步修改。

之后就是写 ES5 势如破竹,攻城拔寨的过程了,最后用永远滴神 Brench Eich 的话来做总结:

最早他们说 JavaScript 没法做「富互联网应用」。

然后他们说 JavaScript 没法快起来。

然后他们说 JavaScript 没法修复语言问题。

然后他们说 JavaScript 没法做多核与 GPU 运算。

他们每次都错了!

我建议:永远押宝在 JS。