|
本文發(fā)布于2011-08-02
有兩個(gè)錯(cuò)誤的觀點(diǎn),其一是“JavaScript在語(yǔ)源上繼承自Cmm”。這個(gè)錯(cuò)誤的觀點(diǎn)主要的來(lái)自于以下途徑(部分):
- 2002年10月7日的《Wired Magazine(連線(xiàn)雜志)》的一份名為“Mother Tongues”的圖;
- O’Reilly公布的“The History of Programming Languages圖;
- Levenez.com公布的“Computer Language History”;
- ……
第二個(gè)錯(cuò)誤的觀點(diǎn),即“Nombas公司的Espresso Pages(濃咖啡版網(wǎng)頁(yè))以及其內(nèi)置的腳本(CEnvi,Cmm語(yǔ)言的開(kāi)發(fā)環(huán)境)是WWW上首次使用的腳本語(yǔ)言”。這個(gè)錯(cuò)誤的觀點(diǎn)主要來(lái)自于:
- 在Nombas網(wǎng)站中關(guān)于Cmm、CEniv以及ScriptEase等技術(shù)與產(chǎn)品的一篇介紹文字;
- Brent Noorda先生(Nombas公司總裁)關(guān)于發(fā)布Espresso Pages的新聞組消息。
這些明顯是不太靠譜的一面之詞。但是進(jìn)一步援引這些內(nèi)容的結(jié)果是:錯(cuò)誤的觀點(diǎn)被一再重述,似乎已經(jīng)快要變成事實(shí)了,例如《JavaScript高級(jí)程序設(shè)計(jì)》一書(shū)已經(jīng)白底黑字地將這些內(nèi)容記述在了“JavaScript簡(jiǎn)史”之中。
本文將簡(jiǎn)明而完整地厘清上述觀點(diǎn)。
一、真相:NETscape早在Espresso Pages發(fā)布之前就實(shí)現(xiàn)了主要的WEB開(kāi)發(fā)特性
首先,這些問(wèn)題的一部分相當(dāng)容易說(shuō)清楚,例如“是不是Espresso Pages首次在WEB中使用了腳本語(yǔ)言”。因?yàn)殛P(guān)于Espresso Pages的這個(gè)新聞組消息還有著明確的時(shí)間(1995.11.27)(*1):
那么,NETscape Navigator 2.0中對(duì)腳本的支持又是如何出現(xiàn)的呢?考察NN2此前發(fā)布的各個(gè)Beta版就可以發(fā)現(xiàn)(*2):至遲到NN2 Beta2,網(wǎng)頁(yè)內(nèi)嵌腳本的概念就相當(dāng)清晰,并且實(shí)現(xiàn)完整了。我們先看看在1995.10.10發(fā)布的NN2 Beta1這個(gè)版本。它能做什么呢?它其實(shí)已經(jīng)具備了標(biāo)簽內(nèi)聯(lián)腳本功能,如下圖所示:
相對(duì)完整的腳本特性,例如<script>標(biāo)簽與function函數(shù)等,則要等到NN beta2才支持,其發(fā)布時(shí)間為1995.11.04:
上面的示例說(shuō)明了beta2中的腳本已經(jīng)開(kāi)始支持在函數(shù)內(nèi)通過(guò)this引用來(lái)得到window對(duì)象,而frames、self這些成員在這時(shí)的window對(duì)象中就已經(jīng)存在,這些事實(shí)上就是最最原始的DOM。
所以,盡管Nombas是搶在了NETscape Navigator 2.0正式發(fā)布(1996.01.23,JavaScript 1.0隨該版本發(fā)布)之前,公開(kāi)了在NN2上嵌入第三方腳本引擎的方式來(lái)實(shí)現(xiàn)的Espresso Pages,但是與我們今天討論的Web開(kāi)發(fā)相關(guān)的一切,在這之前、在NN Beta2中就已成事實(shí)了。而這個(gè)NETscape Navigator Beta2的發(fā)布時(shí)間,比Espresso Pages的發(fā)布早了近一個(gè)月。
《JavaScript高級(jí)程序設(shè)計(jì)》一書(shū)中不但認(rèn)為Espresso Pages是WWW上“首次使用腳本語(yǔ)言的標(biāo)志”,還繼續(xù)講道:
相信當(dāng)初的Nombas公司不太可能意識(shí)到,他們這種網(wǎng)頁(yè)中嵌入腳本的想法會(huì)在很大程度上左右未來(lái)因特網(wǎng)的發(fā)展。
這段“文字游戲”很容易讓讀者將“網(wǎng)頁(yè)嵌入腳本”的設(shè)想歸功于Nombas,以及具體的那個(gè)腳本語(yǔ)言Cmm。但如同上面所說(shuō)的,這種設(shè)想并非源自Espresso Pages。這些想法的確左右了因特網(wǎng)的發(fā)展,但是沒(méi)有任何證據(jù)顯示Nombas與這一起源存在關(guān)系。
二、真相:Cmm與JavaScript完全無(wú)關(guān),而ScriptEase不過(guò)是追隨者
Cmm的確是一種腳本語(yǔ)言,比JavaScript出現(xiàn)得早很多。但這個(gè)腳本語(yǔ)言并不是嵌入式的,它需要一個(gè)名為CEniv的可執(zhí)行程序,來(lái)運(yùn)行這種擴(kuò)展名為.cmm的腳本代碼文件。因?yàn)镃mm一開(kāi)始并沒(méi)有設(shè)計(jì)為嵌入式語(yǔ)言,所以這些稱(chēng)為Espresso Pages的東西其實(shí)是一些可供下載的Demos,使用者需要安裝CEnvi的某個(gè)版本,并通過(guò)一些配置來(lái)使Demo能在NN2 beta中使用。原文是:
but for now these demos use our CEnvi for Windows application as a helper. Instructions are on the page for how to configure, including a download of a demo of the Cmm interpreter.
現(xiàn)在已經(jīng)再也找不到這些下載和操作指南了。不過(guò)我們這里并不想考察Espresso Pages的效果,而是想說(shuō)清他當(dāng)時(shí)所使用的Cmm語(yǔ)言與JavaScript語(yǔ)言有沒(méi)有什么關(guān)系。因?yàn)楫?dāng)時(shí)JavaScript正在開(kāi)發(fā)之中,而Cmm已經(jīng)出現(xiàn)了三年之久,那么JavaScript的語(yǔ)言設(shè)計(jì)是否參考了Cmm呢?
目前可以下載到的CEnvi包括以下版本:
CEnvi 1.0 – 1993.08.09
CEnvi 1.008 – 1993.12.21
CEnvi 1.009 for DOS/Win/OS2 – 1994.11.29
CEnvi 2.0 for DOS/Win/OS2 – 1995.03.29
CEnvi 2.10 for DOS/Win/NT/OS2 – 1995.10.17
CEnvi 2.11 for DOS – 1996.02.20
在NN2之前的是CEnvi 2.0,NN2正式發(fā)布之后則有CEnvi 2.11。我們只需要考察這其中的Cmm語(yǔ)言的特性以及其進(jìn)化的路線(xiàn),就可以了解這一階段中二者可能存在的相互影響。根據(jù)Cmm的語(yǔ)言手冊(cè)(*3),其主要的發(fā)展為:
- 1.0 ~ 2.0:添加了字符串中的轉(zhuǎn)義字符(Escape Sequences for Characters)
- 2.0 ~ 2.1:無(wú)變化
- 2.1 ~ 2.11:無(wú)變化
也就是說(shuō),Cmm語(yǔ)言從1993年隨CEnvi發(fā)布一直到1996年2月,下面的語(yǔ)言特性并沒(méi)有任何實(shí)質(zhì)性的變化:
- 與C語(yǔ)言相似的運(yùn)算符(包括位運(yùn)算、布爾運(yùn)符和三元”?:”運(yùn)算符等)、注釋、字符串表達(dá)方式;
- 有Byte、Integer、Float等數(shù)據(jù)類(lèi)型,不需要預(yù)聲明變量,變量在第一次賦值時(shí)創(chuàng)建并關(guān)聯(lián)類(lèi)型;
- 有數(shù)組與字符串類(lèi)型,數(shù)組不需要預(yù)定義長(zhǎng)度或元素類(lèi)型;字符串是字符類(lèi)型的數(shù)組,可以通過(guò)數(shù)組下標(biāo)存取;可以通過(guò)”...”方式,或用{...}聲明一系列單個(gè)字符的方式來(lái)聲明字符串;
- 有結(jié)構(gòu)(Structures)數(shù)據(jù)類(lèi)型,用“.”字符存取其字段;
- 有if、while、do、switch以及for等等語(yǔ)句,有GOTO語(yǔ)句;
- 可以聲明函數(shù),但不需要用function關(guān)鍵字開(kāi)始,也不需要聲明參數(shù)類(lèi)型,參數(shù)個(gè)數(shù)必須是確定的。
- 有#include與#define等預(yù)聲明語(yǔ)句;在任意函數(shù)之外的代碼為初始化代碼,其聲明的變量為全局變量;在初始化代碼之后執(zhí)行的第一個(gè)函數(shù)為main(ArgCount, ArgStrings)。
可見(jiàn)Cmm語(yǔ)言的多數(shù)概念來(lái)自于C語(yǔ)言,而與JavaScript所體現(xiàn)的面向?qū)ο筇匦院翢o(wú)關(guān)系。例如Cmm的數(shù)組是一個(gè)獨(dú)立的數(shù)據(jù)類(lèi)型,取得數(shù)組的長(zhǎng)度應(yīng)使用GetArraySpan(aArr)函數(shù),而不是取數(shù)組這個(gè)對(duì)象的一個(gè)屬性aArr.length。通過(guò)對(duì)Cmm語(yǔ)言特性的詳細(xì)分析可見(jiàn):即使JavaScript與Cmm存有一些相似的部分,那么最多也是其借鑒自C語(yǔ)言的表達(dá)式運(yùn)算、語(yǔ)句語(yǔ)法等等,而這些并不足以成為“JavaScript語(yǔ)源自Cmm”的證據(jù)。
而在這個(gè)話(huà)題中的另一個(gè)角色,是名為“ScriptEase”的腳本語(yǔ)言,它也是最早符合ECMAScript 262標(biāo)準(zhǔn)的語(yǔ)言之一——簡(jiǎn)單的說(shuō),它也是一個(gè)JavaScript語(yǔ)言。而且,Nombas公司正是因此將Cmm與JavaScript掛上關(guān)系,因?yàn)樗麄兟暦Q(chēng):ScriptEase就是Cmm,只不過(guò)是換了個(gè)名字。
真的只是換了一個(gè)名字這樣簡(jiǎn)單嗎?
此前我們說(shuō)過(guò),Cmm的最后一個(gè)可見(jiàn)的發(fā)布包含在CEnvi 2.11中,發(fā)布時(shí)間是1996.02.20,其語(yǔ)言特性與上述列表一致(沒(méi)有變化)。這個(gè)語(yǔ)言是什么時(shí)候更名的呢?答案是:晚于1997.02.06。因?yàn)樵?997年4月至6月間,Nombas公司發(fā)布了CEnvi的3.0版本,在這個(gè)版本中首次使用到ScriptEase這個(gè)名字,其中的名為HISTORY的文件——該文件被打包的時(shí)間(令人驚奇地)是1997.02.06——描述這次更名的緣由:
那么在這個(gè)版本中的ScriptEase又具有什么樣的語(yǔ)言特性呢?答案是:與Cmm 1.0~2.11相比仍然沒(méi)有變化。對(duì)比該ScriptEase 3.0發(fā)布包中的語(yǔ)言手冊(cè)《The ScriptEase Language》與Cmm 2.11中對(duì)應(yīng)文檔可知:數(shù)組、字符串、函數(shù)、GOTO語(yǔ)句等等一切,仍跟Cmm中一模一樣。
但是這個(gè)原來(lái)叫Cmm的語(yǔ)言搖身一變,改名叫ScriptEase了。現(xiàn)在,請(qǐng)看下面這樣的代碼(語(yǔ)言手冊(cè)對(duì)比,左側(cè)為ScriptEase 3.0 - 1997.04.15文檔,右側(cè)為Cmm 2.11 – 1996.02.20文檔):
相信任何一個(gè)看過(guò)JavaScript代碼的人都會(huì)明白,這個(gè)名為Cmm/ScriptEase的語(yǔ)言,所采用的函數(shù)聲明的語(yǔ)法絕非JavaScript語(yǔ)法,也絕對(duì)不可能符合ECMAScript所定義的規(guī)范。而此時(shí)已是1997年,JavaScript 已經(jīng)發(fā)布了兩年,ECMAScript標(biāo)準(zhǔn)已即將發(fā)布(1997.06)。雖然現(xiàn)在的Cmm已經(jīng)更名為ScriptEase,但在其語(yǔ)言手冊(cè)中仍然找不到Object這樣的詞匯,代碼上仍然使用著最初的函數(shù)聲明語(yǔ)法。
那么,這樣的一門(mén)語(yǔ)言又是何時(shí)搖身一變,以至于被誤認(rèn)為“JavaScript的語(yǔ)源”的呢。這一時(shí)間還要推進(jìn)到半年之后,也就是1997年12月。這時(shí)ScriptEase發(fā)布了它的4.0版,在目前可以找到的一個(gè)名為“ScriptEase:WebServer Edition 4.01 – 1997.12.08”版本中(準(zhǔn)確的說(shuō),我并沒(méi)有找到3.0至4.0的全部發(fā)布過(guò)程),終于有了一份手冊(cè),開(kāi)始采用如下的語(yǔ)法:
正是在這份ScriptEase官方手冊(cè)中,寫(xiě)道:
現(xiàn)在這一切還需要解釋嗎?以下兩個(gè)言論:
- ScriptEase在從3.0到4.0的過(guò)程中,采用了ECMAScript標(biāo)準(zhǔn),進(jìn)而實(shí)現(xiàn)了JavaScript的一個(gè)版本;
- JavaScript語(yǔ)源自Cmm,繼承了后者語(yǔ)言特性
之中,后者是何等的站不住腳?!然而,它正是這樣地畫(huà)在了O’Reilly的圖冊(cè)里(*4):
三、真相:Nombas公司的廣告做得太好
大概是2001年前后,Nombas官方網(wǎng)頁(yè)對(duì)其ScriptEase的介紹中,使用著一份名為“History of ScriptEase and JavaScript”的文檔(*5),但這個(gè)網(wǎng)頁(yè)使用著與該文檔標(biāo)題完全不同的TITLE圖片:
這篇文章的序言寫(xiě)得中規(guī)中矩。大意是說(shuō)1992年到1993年間,Nombas開(kāi)發(fā)了一個(gè)Cmm語(yǔ)言。不過(guò)這里講到了該語(yǔ)言是“embeddable scripting language”,如前所述,這時(shí)的Cmm并沒(méi)有嵌入式的特性。但是從后來(lái)Nombas總是同時(shí)發(fā)布CEniv的不同操作系統(tǒng)平臺(tái)版本來(lái)看,Cmm語(yǔ)言是采用了跨平臺(tái)的語(yǔ)言(例如C)編譯的。而“Cmm隨CEnvi發(fā)布不同平臺(tái)版本”并不能作為它“具有嵌入特性”的充分證據(jù)。再退一步來(lái)看,即使Cmm具備了嵌入式語(yǔ)言特性,可作為獨(dú)立模塊來(lái)嵌入到CEnvi發(fā)布,也并不表明它可以嵌入到后來(lái)的NETscape Navigator中,因?yàn)楹笳咴诋?dāng)時(shí)是閉源的,沒(méi)有可能讓CEnvi來(lái)“嵌入”。
然而這一點(diǎn),在《JavaScript高級(jí)程序設(shè)計(jì)》中被寫(xiě)成:
When the popularity of NETscape Navigator started peaking, Nombas developed a version of CEnvi that could be embedded into web pages.
(在NETscape Navigator受到人們的狂熱追捧之際,Nombas公司開(kāi)發(fā)了能夠嵌入到Web頁(yè)面中的CEnvi版本。)
可惜這并非事實(shí)。關(guān)于這一點(diǎn),Nombas的原文是:
When NETscape's first commercial browsers were released we made a version of CEnvi that could handle short scripts embedded within web pages.(當(dāng)NETscape的第一個(gè)商業(yè)瀏覽器發(fā)布時(shí),我們創(chuàng)建了一個(gè)嵌入在WEB頁(yè)面中的、能夠操作簡(jiǎn)短腳本的CEnvi版本。)
Nombas并沒(méi)有在這里指明“first commercial browsers”是NETscape的哪一個(gè)具體版本。因此這段文字很容易讓人誤解為NN 1.0發(fā)布的時(shí)候,CEnvi就已經(jīng)可以實(shí)現(xiàn)網(wǎng)頁(yè)內(nèi)嵌腳本了。而事實(shí)上,所謂的“CEnvi定制版本”根本就沒(méi)有出現(xiàn)過(guò),即使曾經(jīng)有過(guò),也不過(guò)是Nombas在NN 2.0 beta中玩的一些小手腳。進(jìn)一步地說(shuō),這時(shí)的Cmm、CEnvi以及后文中的"Espresso Pages",都只是Nombas在NN 2.0 Beta發(fā)布階段的一些技術(shù)嘗試而已。
然而,這篇Nombas的原文又繼續(xù)談?wù)?ldquo;網(wǎng)頁(yè)內(nèi)嵌腳本”的一些特點(diǎn)。例如:
By embedded scripts within the page we allowed the client side to handle processing, rather than making all dynamic interaction happen on the server. This brought immediate client-side interaction with the user.(使用網(wǎng)頁(yè)中的嵌入腳本,我們?cè)试S客戶(hù)端控制一些東西,這比讓所有動(dòng)作發(fā)生在服務(wù)器端更好。這強(qiáng)化了客戶(hù)端與用戶(hù)之間的交互。)
這些特性描述也就僅僅是對(duì)這類(lèi)技術(shù)的一個(gè)概述而已,并不表明什么有“原創(chuàng)”、“獨(dú)創(chuàng)”或“初創(chuàng)”的意義(注意這段文字的未尾使用了“句號(hào)”)。但是接下來(lái),Nombas耍了一個(gè)小花招,在文章中說(shuō):
The advantages of client-side handling were made obvious by Nombas' "Espresso Pages", and NETscape soon began work on their own version, which they called LiveScript, and then renamed to JavaScript just before its final release.(Nombas的"Espresso Pages"使客戶(hù)端控制的優(yōu)勢(shì)更加明顯,接下來(lái)(and?)NETscape很快在他們自己的版本上開(kāi)始工作,他們稱(chēng)之為L(zhǎng)iveScript,然后就在正式版本之前更名為JavaScript。)
注意,“NETscape很快在他們自己的版本上開(kāi)始工作”之前的“and”,這里可以理解為“接下來(lái)”,或者“并且”,或者僅僅是語(yǔ)氣上的連貫,但無(wú)論如何,這此前一個(gè)“逗號(hào)”便暗示了“their own version(他們自己的版本)”與前面所述的一切存在“必然的”關(guān)系。然而如本文此前所述的:
- “Espresso Pages”中網(wǎng)頁(yè)內(nèi)嵌腳本的想法,在NN Beta2中就已經(jīng)成熟了,而后者早前了一個(gè)多月就發(fā)布了,談不上受到了“Espresso Pages”的影響。
同樣的,正是由于這個(gè)“and”以及逗號(hào),使得LiveScript與后面的JavaScript“變成了”Cmm的一個(gè)后來(lái)者,被錯(cuò)誤地解讀成了“存在語(yǔ)源上的關(guān)系”。而本文此前的分析說(shuō)明:
- 事實(shí)上是Cmm受到了JavaScript的影響:ScriptEase在從3.0到4.0的過(guò)程中,采用了ECMAScript標(biāo)準(zhǔn),進(jìn)而實(shí)現(xiàn)了JavaScript的一個(gè)版本。
正是Nombas原文中的措辭,不可避免地讓人認(rèn)為L(zhǎng)iveScript是基于"Espresso Pages"思想的(或受到其影響的)一個(gè)版本,進(jìn)而發(fā)展成為JavaScript。但是事實(shí)上:
- JavaScript最早被稱(chēng)為Mocha(魔卡),這是項(xiàng)目的代碼名。這個(gè)名字一直用到NN2.0 beta 2發(fā)布之前(95.11.04)——包括在beta 1中彈出的錯(cuò)誤框上,還可以看到Mocha的名字。
- NN2.0 beta2發(fā)布的時(shí)候使用了LiveScript這個(gè)內(nèi)部名稱(chēng)。
- 隨后NETscape與SUN共同發(fā)布聲明(1995.12.04),正式啟用了JavaScript這個(gè)名字。直到NN2.0 beta4發(fā)布時(shí)(1995.12.20),其文檔與軟件界面中才開(kāi)始統(tǒng)一使用JavaScript這個(gè)名字。
這一切,與“Espresso Pages”是否出現(xiàn),有什么樣的關(guān)系嗎?——毫無(wú)關(guān)聯(lián)!
四、最后的定論,Brendan Eich的澄清
在Wiki Talk中保留著B(niǎo)rendan Eich的一段對(duì)話(huà)(*6),足以為Cmm與JavaScript之間的關(guān)系做最終的澄清。
Hello. I first met Brent Noorda in late 1996, when NETscape brought JavaScript to ECMA for standardization. I had never heard of NOMBAS or its products before then. When I created JS in May 1995 (in about ten days for the core language implementation; the rest of that year was consumed by the DOM and browser embedding work), my influences were awk, C, HyperTalk, and Self, combined with management orders to "make it look like Java."
其一是與Cmm/Nombas的關(guān)系:
我第一次見(jiàn)到Brent Noorda是在1996年底,……在此之前我從未聽(tīng)說(shuō)過(guò)NOMBAS或它的產(chǎn)品。
其二是JS語(yǔ)言的創(chuàng)建過(guò)程,以及大概的時(shí)間:
在1995年5月開(kāi)始創(chuàng)建JS的時(shí)候(大約10天用于核心語(yǔ)言實(shí)現(xiàn),其它的時(shí)間主要是用在DOM以及瀏覽器嵌入方面)。
其三是關(guān)于JS語(yǔ)源的最終結(jié)論:
我的影響主要來(lái)自于awk、C、HyperTalk和Self,以及主管們所要求的“使它看起來(lái)像Java一點(diǎn)”。
關(guān)于第三點(diǎn),JavaScript“像”Java,而不是“語(yǔ)源自”Java,可以由《JavaScript Working Document 1.0》(1996.01.22),以及其原始的、NETscape公司的官方文檔《JavaScript Authoring Guide》文檔中的原文(*7):
以佐證。JavaScript在語(yǔ)法上與Java、Awk和Perl都有一定“形似”,這可以由《JavaScript Language Specification V1.1》(1996.11.18,Brendan Eich參與編訂)文檔中的原文(*8):
Borrows most of its syntax from Java, but also inherites from Awk and Perl
以佐證。最后,關(guān)于Brendan Eich所言:
my influences were awk, C, HyperTalk, and Self
其中的關(guān)鍵語(yǔ)言特性——原型繼承、動(dòng)態(tài)類(lèi)型和動(dòng)態(tài)數(shù)據(jù)綁定等,并未出現(xiàn)在NETscape Navigator 2.0及其中的JavaScript 1.0中,因此這里不再詳究。
參考:
*1:http://embedded.eecs.berkeley.edu/Respep/Research/dds/Hyper-RNweb/0052.html
*2:關(guān)于NETscape Navigator 2.0,其Beta版的發(fā)布時(shí)間采用安裝包文件的打包時(shí)間,其正式版的發(fā)布時(shí)間采用官方公告時(shí)間。
*3:關(guān)于Cmm語(yǔ)言的特性與版本變更的相關(guān)結(jié)論,是通過(guò)對(duì)照各個(gè)CEnvi版本中的Cmm語(yǔ)言手冊(cè)(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
相關(guān)文章:還原JavaScript的真實(shí)歷史
it知識(shí)庫(kù):詳圖實(shí)證:再談JavaScript的語(yǔ)源問(wèn)題,轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。