問題 ============ JavaScript真的繼承自Cmm嗎? JavaScript與Java有多少關係? JavaScirpt最初的設計是怎樣的?
在許多資料,JavaScript的語源被追溯到一種名為Cmm的語言。同樣是在這一溯源的過程中,人 們發現“其實”JavaScript不是第一種網頁中的指令碼語言。現在一些所謂“公認”的情況是這樣的: ---------------- 大概在1992年,一家稱作Nombas的公司開始開發一種叫做C減減(C-minus-minus,簡稱Cmm)的 嵌入式指令碼語言。這個指令碼語言捆綁在一個叫做CEnvi的共享軟體產品中,當Netscape Navigator 嶄露頭角時,Nombas開發了一個可以嵌入網頁中的CEnvi的版本。這些早期的試驗稱為Espresso Page(濃咖啡般的頁面),它們代表了第一個在全球資訊網上使用的客戶端指令碼語言。而Nombas絲毫 沒有料到它的理念將會成為因特網的一塊重要基石。 ----------------
然而,這是真實的情況嗎?執行在Netscape中的第一個“客戶端指令碼語言”真的是Cmm的濃咖啡? 又或者真的象Wiki中記述的那樣,Brendan Eich在JavaScript引用了Cmm語言特性?
不是的。儘管上述的資料看起來出權威:《Javascript高階程式設計》(Professional JavaScript for Web Developers),但他的確錯了。
JavaScript與Cmm在語言特性上無關 ============ 為了弄明白JavaScript與Cmm的關係,我大概用了三天的時間,從網上收集了多個Cmm的版本。這 些版本既包括早期的Cmm(1993年),也包括在JavaScript初創時的Cmm(1995年),還包括在後來, Cmm更名為ScriptEase的第一個版本(3.0, 1997年),作為參考,我還考察了它在伺服器端的版本。
遺憾的是,在1996年之前,在Cmm的2.x的最後一個版本之前,Cmm都並不是一個物件導向(或基於 物件)的語言,Cmm正如它自己的名字所說的一樣:是一個精減版的C,而不是C++或以C++為基礎 的變種。所以Cmm中有“結構”,也有#include等,整個的體系是參考C語言的。
由於JavaScript在基本的語法特性(例如大括號、語句關鍵字等)上參考了C,在物件系統上(例 如“.”作為成員存取)上參考了Java,因此在一定程度上Cmm與JavaScript存在相似性——主要是 與共同借鑑自C的部分。但是除了這些之外,JavaScript與Cmm在語言特性上完全無關。
JavaScript最初的基本設計是怎樣的? ============ 我需要補充一下JavaScript初始設計目標。Brendan Eich在1995年4月前後被Netscape公司僱傭, 目標是完成一套語言系統。最初的設計裡,該語言系統是為Netscape的LiveWire戰略服務的。該 戰略彰顯了Netscape當年的勃勃野心,它是Netscape公司的一個通用的Web開發環境,包括Netscape Enterprise、FastTrack Server等。LiveWire架構也成為所有Web伺服器提供SP(Server Page)技 術的藍本。例如在IIS中的ASP,以及更早期的IDC(Internet Database Connect)。
這種技術在伺服器端通過內嵌於網頁的LiveScript程式碼,使用名為database、DbPool、Cursor等 的一組物件來存取LiveWire Database。作為整套的解決方案,Netscape在客戶端網頁上也提供 LiveScript指令碼語言的支援,除了訪問Array、String等這些內建物件之外,也可以訪問window等 瀏覽器物件。
不過並不清楚的是:LiveScript最初的設計是先考慮伺服器端應用,還是先考慮網頁中應用。但這 些應用環境的決策上的變化,時間僅僅限制在1995年4月至1995年10月之前,因為當月釋出的netscape 2.0 beta1已經包含了指令碼支援。
在netscape 2.0 beta1中並不支援<script>標籤,而只是在form表單元素中支援了onclick這類的 事件。這時的指令碼程式碼是用在HTML標籤屬性上的,也就是類似於: <input type="button" οnclick="alert('hello, world!')"> 很快,三週之後netscape 就釋出了beta2。這個版本正式地支援了<script>標籤,並可以解析該標籤 中的程式碼、識別符號,開始具備呼叫函式、表示式運算等能力。這個版本已經具備了JavaScript 1.0 的基本性質。
——什麼?能呼叫函式、表示式運算就是JavaScript 1.0的基本性質了?
是的,差不多了。相比起來,JavaScript 1.0只是在這樣的基礎上加上了一套物件系統而已。在隨 後釋出的beta 3中,函式可以作為構造器使用,可以建立出使用者自己的物件來了。再後來window等 全域性物件被加了進來,再把“當前網頁”中的表單元素等影射成可程式設計物件,JavaScript 1.0就完 成了。
僅僅如此而已。在JavaScript 1.0的時代,既沒有“原型繼承”,也沒有“函數語言程式設計”——甚至 連匿名函式也沒有支援,所以下面的程式碼就足夠讓瀏覽器掛掉了: ---------------- var func = function() { } ----------------
JavaScript 1.0的設計目標,就是“讓網頁動起來”,最初的要求包括三個方面: - 讓網頁中的元素可以被程式設計,所以象forms、links這些物件,在網頁裝載結束後就初始化為全 局成員了——那時候還沒有所謂的DOM或DHTML呢。 - 讓JavaScript跟Java接近一些,因為Netscape與Sun有戰略合作。而且,Sun那時相當火暴。 - 讓JavaScript可以在伺服器與客戶端兩邊都使用,因此它必須是嵌入式的。
不過JavaScript的另一項特性,則自它的第一個版本就存在。該特性就是動態執行,也就是eval()。 這是與它的“指令碼”的性質有關的。在早期的“指令碼”也被稱為“批處理程式”,就如同DOS批處理 或Unix shell一樣,指令碼應當具有裝入字串文字並“動態執行”的能力。
所以總結起來,JavaScript 1.0其實是一個可以建立和操作物件的普通過程式語言。這個時候的JS 程式碼既不能檢測“物件-構造器”之間的繼承性,也沒有原型繼承這樣的東東來構建物件系統。函式 除了在new MyObject()時協助傳入一個this引用之外,就跟普通的函式完全一樣。而且,最為有趣 的是,Brendan Eich這時還沒有形成JavaScript中最重要的“型別系統”概念,此時undefined還只 是系統全域性中的一個特殊的值,而不是某種型別。typeof關鍵字也還根本不存在。換言之,Eich現 在要做的只是一個“可程式設計的、可以用物件的”指令碼語言,至於它是否在型別系統上完備或者優美, 他還顧不過來呢。
JavaScript最重要的“構造器-原型繼承”概念是在JavaScript 1.1版本中提出的,型別系統和重要 的函式式語言特性要等到v1.2之後才被加入。而現在,在1996年1月底,JavaScript 1.0隨Netscape 2.0正式版釋出了。
JavaScript的名字 ============ 為了弄清楚JavaScript名稱和語言特性的演變,我下載了netscape 2.0 beta1~6,以及2.0~2.02所 有版本的釋出檔案,並逐一安裝測試。下面解釋JavaScript名字的演變過程。
JavaScript最早是被稱為Mocha(魔卡)的,這是這個專案的程式碼名。這個名字一直用到Netscape 2.0 beta 2釋出之前(95.11.04)——包括在beta 1中彈出的錯誤框上,還可以看到Mocha的名字。 不過,早在此前的9月18號,netscape就已經發布訊息將在LiveWire中啟用一種伺服器端指令碼(未 提及名稱)。又因為我們前面提到的“前後端通用指令碼”的設計,該語言在beta 2釋出時就使用 了內部名稱LiveScript。
但同樣混亂的事情是,事實上這時Netscape已經決定將該語言命名為“JavaScript”。因此在 beta 2的釋出備忘中該語言稱為JavaScript,而介面上卻從Mocha改為了LiveScript。這一局面一 直持續到12月4日,netscape與sun共同釋出宣告,正式啟用了JavaScript這個名字。隨後beta 4 釋出(95.12.20),介面和文件上就統一了。
所以事實上“LiveScript”這個名字可以考證的生命週期,也就只有一個月的時間(在95.11.04 - 12.04)。但Mocha畢竟只是專案程式碼名,而非產品名,所以後來人們追溯JavaScript的歷史, 大多隻提到LiveScript為止。
第一段網頁內指令碼真的是濃咖啡(Espresso Page)嗎? ============ 如上面所述的,Netscape 2.0的beta 1中就正式加入了指令碼支援,最遲在beta 2之前。物件的構 建方式、<script>標籤的使用,以及在HTML標籤上使用onclick這類事件控制程式碼……這些設計就已經 被明確了。這些是一直延續到現在的,我們最主要的使用網頁的方式。
那麼,這個時間點可以不容置疑的被確定在95.11.04之前(beta 2釋出之前)。
我們現在再回過頭來看那份講述Espresso Page的訊息。這其實是由Brent Noorda先生(Nombas公 司總裁)於1995.11.27日釋出在新聞組上(comp.infosystems.www.authoring.html)上的一則訊息, 原文是“這週末我們將放出一些Espresso Pages在我們的網站上(This weekend we put up the Espresso Pages, at...)”,那麼,也就是Espresso Pages其實出現在11.30號之後。這已經遠遠 晚於上面的時間了。
也就是說,真正第一種在Netscape中使用的客戶端指令碼,仍然是由Brendan Eich編寫的JavaScript。 這種指令碼使用“<script>”標籤(在伺服器端使用<server>標籤),支援五種基本型別(除undefined 之外),支援自定義物件和構造器等基本特性,能夠操作網頁中內嵌的links、forms等物件。
然而需要繼承說明的是,由於Nombas早早地就實現了Cmm語言以及其開發環境,所以他不需要花什麼 力氣就可以將它們移植到網頁中去並展示其非常豐富的能力。所以在Brent Noorda先生在上面的訊息 中說,(週末放出的)這個Demo將演示 - a bouncy-button game, - real-time verification of user input into forms, - an animated stick-figure, - and a way cool flashback into the psychadellic sixties. 的確,這些演示的功能大概是當時的JavaScript(LiveScript)不能實現的。但相同的功能所需求的 特性以及其基本實現,其實正是Netscape當時已經發布的版本所包含的。所以這裡根本就不存在 Netscape抄襲Nombas的問題。然而換一個角度來想,Nombas可能正是看到Netscape釋出版本中的種 種特性,其實能夠用一個嵌入到瀏覽器中的CEnvi來完成,因此釋出了這樣的一個示範版本。
從時間先後來分析,我們可以確信的是: - Netscape在網頁中嵌入指令碼是早在Espresso Pages出現之前的一個構想; - JavaScript(LiveScript)是真正的第一個在全球資訊網上使用的客戶端指令碼語言。
無論如何,Espresso Pages很好地展示了Netscape當時正在圖謀的構想——不管是Nombas是與Netscape 想到了一起,還是Nombas幫助Netscape展開了(由Netscape設計的)藍圖。在當時(JavaScript 1.0發 布之前),CEnvi中的Cmm相當完善,開發環境也很成熟。所以可以承認的是,Nombas的Espresso Pages 的確更好地展示了Web的末來。但是,成為“因特網的一塊重要基石”的構想——這裡指頁面內指令碼,絕 不是Nombas先創的理念。因為Netscape beta1~3中已經把這些理念都展示了出來。
其它 ============ 有一種Java的編譯器也名為Mocha,但與本文中沒有什麼關係。 Cmm也稱為C--,但另外還有一種名為Sphinx C--的語言,其設計目標與Cmm類似,但不是同一種語言。
在Java熱火的時代裡,出現了很多以濃咖啡(Espresso)命名的產品,但都不是這裡的Espresso Pages。 Espresso Pages只是一些Demo頁面,需要下載並專用安裝一個CEnvi的特定版本才能檢視。但這個特定版 本在網際網路上已經絕跡了。
JavaScript並沒有從Java中尋找太多靈感,Brendan Eich自己說“my influences were awk, C, HyperTalk, and Self”,這其中既不包括 Java,也沒有Cmm的影子。不過Brendan Eich也說另外的影響是“combined with management orders to "make it look like Java."這強調的是一種形似,而不是語源上的承繼關係。
在1996年2月,CEnvi釋出了最後一個2.x版本。這個版本是對以前版本的一些修補。但接下來,過了約一年 半之後,CEnvi才釋出下一個版本(v3.0)。從這個版本開始更名為ScriptEase,放棄了舊有的Cmm規格,而 採用了JavaScript規範下的語法。並且自這個版本開始,ScriptEase釋出Desktop和Web Server等多種不同 的版本——此前CEnvi只有針對不同的作業系統的版本。所以事實上,非但不是Brendan Eich受到了Nombas 的影響,反而是Nombas受JavaScript而放棄了整個原來的語言設計,而且在產品策略上,還抄襲了Netscape 的LiveWire戰略。
Nombas後來被收購掉,ScriptEase等系列產品不再維護。Nombas.com網站仍然可以訪問,但只有一個告別頁 面,不過相應的,Netscape也好不到哪裡去。
Mozilla是Netscape一個早期的Java開發團隊的內部程式碼名。在Netscape 2.0 beta中包含的Java程式碼包中, 就已經可以看到這一標誌了。不過該團隊真正獨立出來成為開源組織,並最終接手Netscape未竟事業,則 是晚至1998年1月以後的事了。
Mozilla與Mozilla Firefox使用兩套版本編號。所以“Mozilla 2”是2006.10月開始發起的,而當時Mozilla Firefox 2.0b1已經發布了——它基於“Mozilla 1”的維護版本。同樣有趣的是,Mozilla Firefox 3.x則在 基於“Mozilla 2”這個專案開發,大概,在2008年中期會發布正式版本。