本文发布于2011-08-02 有两个错误的观点,其一是“JavaScript在语源上继承自Cmm”。这个错误的观点主要的来自于以下途径(部分):
第二个错误的观点,即“Nombas公司的Espresso Pages(浓咖啡版网页)以及其内置的脚本(CEnvi,Cmm语言的开发环境)是WWW上首次使用的脚本语言”。这个错误的观点主要来自于:
这些明显是不太靠谱的一面之词。但是进一步援引这些内容的结果是:错误的观点被一再重述,似乎已经快要变成事实了,例如《JavaScript高级程序设计》一书已经白底黑字地将这些内容记述在了“JavaScript简史”之中。 本文将简明而完整地厘清上述观点。 一、真相:Netscape早在Espresso Pages发布之前就实现了主要的WEB开发特性首先,这些问题的一部分相当容易说清楚,例如“是不是Espresso Pages首次在WEB中使用了脚本语言”。因为关于Espresso Pages的这个新闻组消息还有着明确的时间(1995.11.27)(*1): 那么,Netscape Navigator 2.0中对脚本的支持又是如何出现的呢?考察NN2此前发布的各个Beta版就可以发现(*2):至迟到NN2 Beta2,网页内嵌脚本的概念就相当清晰,并且实现完整了。我们先看看在1995.10.10发布的NN2 Beta1这个版本。它能做什么呢?它其实已经具备了标签内联脚本功能,如下图所示: 相对完整的脚本特性,例如<script>标签与function函数等,则要等到NN beta2才支持,其发布时间为1995.11.04: 上面的示例说明了beta2中的脚本已经开始支持在函数内通过this引用来得到window对象,而frames、self这些成员在这时的window对象中就已经存在,这些事实上就是最最原始的DOM。 所以,尽管Nombas是抢在了Netscape Navigator 2.0正式发布(1996.01.23,JavaScript 1.0随该版本发布)之前,公开了在NN2上嵌入第三方脚本引擎的方式来实现的Espresso Pages,但是与我们今天讨论的Web开发相关的一切,在这之前、在NN Beta2中就已成事实了。而这个Netscape Navigator Beta2的发布时间,比Espresso Pages的发布早了近一个月。 《JavaScript高级程序设计》一书中不但认为Espresso Pages是WWW上“首次使用脚本语言的标志”,还继续讲道:
这段“文字游戏”很容易让读者将“网页嵌入脚本”的设想归功于Nombas,以及具体的那个脚本语言Cmm。但如同上面所说的,这种设想并非源自Espresso Pages。这些想法的确左右了因特网的发展,但是没有任何证据显示Nombas与这一起源存在关系。 二、真相:Cmm与JavaScript完全无关,而ScriptEase不过是追随者Cmm的确是一种脚本语言,比JavaScript出现得早很多。但这个脚本语言并不是嵌入式的,它需要一个名为CEniv的可执行程序,来运行这种扩展名为.cmm的脚本代码文件。因为Cmm一开始并没有设计为嵌入式语言,所以这些称为Espresso Pages的东西其实是一些可供下载的Demos,使用者需要安装CEnvi的某个版本,并通过一些配置来使Demo能在NN2 beta中使用。原文是:
现在已经再也找不到这些下载和操作指南了。不过我们这里并不想考察Espresso Pages的效果,而是想说清他当时所使用的Cmm语言与JavaScript语言有没有什么关系。因为当时JavaScript正在开发之中,而Cmm已经出现了三年之久,那么JavaScript的语言设计是否参考了Cmm呢? 目前可以下载到的CEnvi包括以下版本:
在NN2之前的是CEnvi 2.0,NN2正式发布之后则有CEnvi 2.11。我们只需要考察这其中的Cmm语言的特性以及其进化的路线,就可以了解这一阶段中二者可能存在的相互影响。根据Cmm的语言手册(*3),其主要的发展为:
也就是说,Cmm语言从1993年随CEnvi发布一直到1996年2月,下面的语言特性并没有任何实质性的变化:
可见Cmm语言的多数概念来自于C语言,而与JavaScript所体现的面向对象特性毫无关系。例如Cmm的数组是一个独立的数据类型,取得数组的长度应使用GetArraySpan(aArr)函数,而不是取数组这个对象的一个属性aArr.length。通过对Cmm语言特性的详细分析可见:即使JavaScript与Cmm存有一些相似的部分,那么最多也是其借鉴自C语言的表达式运算、语句语法等等,而这些并不足以成为“JavaScript语源自Cmm”的证据。 而在这个话题中的另一个角色,是名为“ScriptEase”的脚本语言,它也是最早符合ECMAScript 262标准的语言之一——简单的说,它也是一个JavaScript语言。而且,Nombas公司正是因此将Cmm与JavaScript挂上关系,因为他们声称:ScriptEase就是Cmm,只不过是换了个名字。 真的只是换了一个名字这样简单吗? 此前我们说过,Cmm的最后一个可见的发布包含在CEnvi 2.11中,发布时间是1996.02.20,其语言特性与上述列表一致(没有变化)。这个语言是什么时候更名的呢?答案是:晚于1997.02.06。因为在1997年4月至6月间,Nombas公司发布了CEnvi的3.0版本,在这个版本中首次使用到ScriptEase这个名字,其中的名为HISTORY的文件——该文件被打包的时间(令人惊奇地)是1997.02.06——描述这次更名的缘由: 那么在这个版本中的ScriptEase又具有什么样的语言特性呢?答案是:与Cmm 1.0~2.11相比仍然没有变化。对比该ScriptEase 3.0发布包中的语言手册《The ScriptEase Language》与Cmm 2.11中对应文档可知:数组、字符串、函数、GOTO语句等等一切,仍跟Cmm中一模一样。 但是这个原来叫Cmm的语言摇身一变,改名叫ScriptEase了。现在,请看下面这样的代码(语言手册对比,左侧为ScriptEase 3.0 - 1997.04.15文档,右侧为Cmm 2.11 – 1996.02.20文档): 相信任何一个看过JavaScript代码的人都会明白,这个名为Cmm/ScriptEase的语言,所采用的函数声明的语法绝非JavaScript语法,也绝对不可能符合ECMAScript所定义的规范。而此时已是1997年,JavaScript 已经发布了两年,ECMAScript标准已即将发布(1997.06)。虽然现在的Cmm已经更名为ScriptEase,但在其语言手册中仍然找不到Object这样的词汇,代码上仍然使用着最初的函数声明语法。 那么,这样的一门语言又是何时摇身一变,以至于被误认为“JavaScript的语源”的呢。这一时间还要推进到半年之后,也就是1997年12月。这时ScriptEase发布了它的4.0版,在目前可以找到的一个名为“ScriptEase:WebServer Edition 4.01 – 1997.12.08”版本中(准确的说,我并没有找到3.0至4.0的全部发布过程),终于有了一份手册,开始采用如下的语法: 正是在这份ScriptEase官方手册中,写道: 现在这一切还需要解释吗?以下两个言论:
之中,后者是何等的站不住脚?!然而,它正是这样地画在了O’Reilly的图册里(*4): 三、真相:Nombas公司的广告做得太好大概是2001年前后,Nombas官方网页对其ScriptEase的介绍中,使用着一份名为“History of ScriptEase and JavaScript”的文档(*5),但这个网页使用着与该文档标题完全不同的TITLE图片: 这篇文章的序言写得中规中矩。大意是说1992年到1993年间,Nombas开发了一个Cmm语言。不过这里讲到了该语言是“embeddable scripting language”,如前所述,这时的Cmm并没有嵌入式的特性。但是从后来Nombas总是同时发布CEniv的不同操作系统平台版本来看,Cmm语言是采用了跨平台的语言(例如C)编译的。而“Cmm随CEnvi发布不同平台版本”并不能作为它“具有嵌入特性”的充分证据。再退一步来看,即使Cmm具备了嵌入式语言特性,可作为独立模块来嵌入到CEnvi发布,也并不表明它可以嵌入到后来的Netscape Navigator中,因为后者在当时是闭源的,没有可能让CEnvi来“嵌入”。 然而这一点,在《JavaScript高级程序设计》中被写成:
可惜这并非事实。关于这一点,Nombas的原文是:
Nombas并没有在这里指明“first commercial browsers”是Netscape的哪一个具体版本。因此这段文字很容易让人误解为NN 1.0发布的时候,CEnvi就已经可以实现网页内嵌脚本了。而事实上,所谓的“CEnvi定制版本”根本就没有出现过,即使曾经有过,也不过是Nombas在NN 2.0 beta中玩的一些小手脚。进一步地说,这时的Cmm、CEnvi以及后文中的"Espresso Pages",都只是Nombas在NN 2.0 Beta发布阶段的一些技术尝试而已。 然而,这篇Nombas的原文又继续谈论“网页内嵌脚本”的一些特点。例如:
这些特性描述也就仅仅是对这类技术的一个概述而已,并不表明什么有“原创”、“独创”或“初创”的意义(注意这段文字的未尾使用了“句号”)。但是接下来,Nombas耍了一个小花招,在文章中说:
注意,“Netscape很快在他们自己的版本上开始工作”之前的“and”,这里可以理解为“接下来”,或者“并且”,或者仅仅是语气上的连贯,但无论如何,这此前一个“逗号”便暗示了“their own version(他们自己的版本)”与前面所述的一切存在“必然的”关系。然而如本文此前所述的:
同样的,正是由于这个“and”以及逗号,使得LiveScript与后面的JavaScript“变成了”Cmm的一个后来者,被错误地解读成了“存在语源上的关系”。而本文此前的分析说明:
正是Nombas原文中的措辞,不可避免地让人认为LiveScript是基于"Espresso Pages"思想的(或受到其影响的)一个版本,进而发展成为JavaScript。但是事实上:
这一切,与“Espresso Pages”是否出现,有什么样的关系吗?——毫无关联! 四、最后的定论,Brendan Eich的澄清在Wiki Talk中保留着Brendan Eich的一段对话(*6),足以为Cmm与JavaScript之间的关系做最终的澄清。
其一是与Cmm/Nombas的关系:
其二是JS语言的创建过程,以及大概的时间:
其三是关于JS语源的最终结论:
关于第三点,JavaScript“像”Java,而不是“语源自”Java,可以由《JavaScript Working Document 1.0》(1996.01.22),以及其原始的、Netscape公司的官方文档《JavaScript Authoring Guide》文档中的原文(*7):
以佐证。JavaScript在语法上与Java、Awk和Perl都有一定“形似”,这可以由《JavaScript Language Specification V1.1》(1996.11.18,Brendan Eich参与编订)文档中的原文(*8):
以佐证。最后,关于Brendan Eich所言:
其中的关键语言特性——原型继承、动态类型和动态数据绑定等,并未出现在Netscape Navigator 2.0及其中的JavaScript 1.0中,因此这里不再详究。 参考: *1:http://embedded.eecs.berkeley.edu/Respep/Research/dds/Hyper-RNweb/0052.html *2:关于Netscape Navigator 2.0,其Beta版的发布时间采用安装包文件的打包时间,其正式版的发布时间采用官方公告时间。 *3:关于Cmm语言的特性与版本变更的相关结论,是通过对照各个CEnvi版本中的Cmm语言手册(CEnvi Demo Manual, Chapter 2: Cmm Language Tutorial)而得出的。 *4:http://oreilly.com/news/languageposter_0504.html *5:http://www.nombas.com/us/scripting/history.htm *6:http://en.wikipedia.org/wiki/Talk:ECMAScript#Origins_of_LiveScript *7:http://tecfa.unige.ch/guides/js/js10.pdf *8:http://www.planetpdf.com/codecuts/pdfs/tutorial/jsspec.pdf 相关文章:还原JavaScript的真实历史 |