雖然 JavaScript 和 ECMAScript 通常都被人們用來表達相同的含義,但 JavaScript 的含義卻比 ECMA-262 中規定的要多得多。沒錯,一個完整的 JavaScript 實現應該由下列三個不同的部分組成(見圖 1-1)。
核心(ECMAScript)
文檔對象模型(DOM)
瀏覽器對象模型(BOM)
1.2.1 ECMAScript
由 ECMA-262 定義的 ECMAScript 與 Web 瀏覽器沒有依賴關系。實際上,這門語言本身并不包含輸入和輸出定義。 ECMA-262 定義的只是這門語言的基礎,而在此基礎之上可以構建更完善的腳本語言。
我們常見的 Web 瀏覽器只是 ECMAScript 實現可能的宿主環境之一。宿主環境不僅提供基本的ECMAScript 實現,同時也會提供該語言的擴展,以便語言與環境之間對接交互。而這些擴展——如DOM,則利用 ECMAScript 的核心類型和語法提供更多更具體的功能,以便實現針對環境的操作。其他宿主環境包括 Node(一種服務端 JavaScript 平臺)和 Adobe Flash。既然 ECMA-262 標準沒有參照 Web 瀏覽器,那它都規定了些什么內容呢?大致說來,它規定了這門語言的下列組成部分:
語法
類型
語句
關鍵字
保留字
操作符
對象
ECMAScript 就是對實現該標準規定的各個方面內容的語言的描述。 JavaScript 實現了 ECMAScript,Adobe ActionScript 同樣也實現了 ECMAScript。
1. ECMAScript 的版本
ECMAScript 的不同版本又稱為版次,以第 x 版表示(意即描述特定實現的 ECMA-262 規范的第 x個版本)。 ECMA-262 的最近一版是第 5 版,發布于 2009 年。而 ECMA-262 的第 1 版本質上與 Netscape的 JavaScript 1.1 相同——只不過刪除了所有針對瀏覽器的代碼并作了一些較小的改動: ECMA-262 要求支持 Unicode 標準(從而支持多語言開發),而且對象也變成了平臺無關的(Netscape JavaScript 1.1 的對象在不同平臺中的實現不一樣,例如 Date 對象) 。這也是 JavaScript 1.1 和 1.2 與 ECMA-262 第 1 版不一致的主要原因。
ECMA-262 第 2 版主要是編輯加工的結果。這一版中內容的更新是為了與 ISO/IEC-16262 保持嚴格一致,沒有作任何新增、修改或刪節處理。因此,一般不使用第 2 版來衡量 ECMAScript 實現的兼容性。ECMA-262 第 3 版才是對該標準第一次真正的修改。修改的內容涉及字符串處理、錯誤定義和數值輸出。這一版還新增了對正則表達式、新控制語句、 try-catch 異常處理的支持,并圍繞標準的國際化做出了一些小的修改。從各方面綜合來看,第 3 版標志著 ECMAScript 成為了一門真正的編程語言。
ECMA-262 第 4 版對這門語言進行了一次全面的檢核修訂。由于 JavaScript 在 Web 上日益流行,開發人員紛紛建議修訂 ECMAScript,以使其能夠滿足不斷增長的 Web 開發需求。作為回應, ECMA TC39重新召集相關人員共同謀劃這門語言的未來。結果,出臺后的標準幾乎在第 3 版基礎上完全定義了一門新語言。第 4 版不僅包含了強類型變量、新語句和新數據結構、真正的類和經典繼承,還定義了與數據交互的新方式。
與此同時, TC39 下屬的一個小組也提出了一個名為 ECMAScript 3.1 的替代性建議,該建議只對這門語言進行了較少的改進。這個小組認為第 4 版給這門語言帶來的跨越太大了。因此,該小組建議對這門語言進行小幅修訂,能夠在現有 JavaScript 引擎基礎上實現。最終, ES3.1 附屬委員會獲得的支持超過了 TC39,ECMA-262 第 4 版在正式發布前被放棄。
ECMAScript 3.1 成為 ECMA-262 第 5 版,并于 2009 年 12 月 3 日正式發布。第 5 版力求澄清第 3版中已知的歧義并增添了新的功能。新功能包括原生 JSON 對象(用于解析和序列化 JSON 數據)、繼承的方法和高級屬性定義,另外還包含一種嚴格模式,對 ECMAScript 引擎解釋和執行代碼進行了補充說明。
2. 什么是 ECMAScript 兼容
ECMA-262 給出了 ECMAScript 兼容的定義。要想成為 ECMAScript 的實現,則該實現必須做到:
支持 ECMA-262 描述的所有“類型、值、對象、屬性、函數以及程序句法和語義”(ECMA-262第 1 頁);
支持 Unicode 字符標準。
此外,兼容的實現還可以進行下列擴展。
添加 ECMA-262 沒有描述的“更多類型、值、對象、屬性和函數”。 ECMA-262 所說的這些新增特性,主要是指該標準中沒有規定的新對象和對象的新屬性。
支持 ECMA-262 沒有定義的“程序和正則表達式語法”。(也就是說,可以修改和擴展內置的正則表達式語法。)
上述要求為兼容實現的開發人員基于 ECMAScript 開發一門新語言提供了廣闊的空間和極大的靈活性,這也從另一個側面說明了 ECMAScript 受開發人員歡迎的原因。
3. Web 瀏覽器對 ECMAScript 的支持
1996 年, Netscape Navigator 3 捆綁發布了 JavaScript 1.1。而相同的 JavaScript 1.1 設計規范隨后作為對新標準(ECMA-262)的建議被提交給 Ecma。伴隨著 JavaScript 的迅速走紅, Netscape 豪情滿懷地著手開發 JavaScript 1.2。然而,問題是 Ecma 當時還沒有接受 Netscape 的建議。
Netscape Navigator 3 發布后不久,微軟也推出了 Internet Explorer 3。微軟在 IE 的這一版中捆綁了JScript 1.0,很多人都認為 JScript 1.0 與 JavaScript 1.1 應該是一樣的。但是,由于沒有文檔依據,加之不適當的特性模仿, JScript 1.0 還是很難與 JavaScript 1.1 相提并論。
1997 年,內置 JavaScript 1.2 的 Netscape Navigator 4 發布;而到這一年年底, ECMA-262 第 1 版也被接受并實現了標準化。結果,雖然 ECMAScript 被認為是基于 JavaScript 1.1 制定的,但 JavaScript 1.2與 ECMAScript 的第 1 版并不兼容。
JScript 的升級版是 Internet Explorer 4 中內置的 JScript 3.0(隨同微軟 IIS 3.0 發布的 JScript 2.0 從來也沒有移植到瀏覽器中)。微軟通過媒體大肆宣傳 JScript 3.0 是世界上第一個 ECMA 兼容的腳本語言,但當時的 ECMA-262 尚未定稿。于是, JScript 3.0 與 JavaScript 1.2 都遭遇了相同的尷尬局面——誰都沒有按照最終的 ECMAScript 標準來實現。
Netscape 決定更新其 JavaScript 實現,即在 Netscape Navigator 4.06 中發布 JavaScript 1.3,從而做到了與 ECMA-262 的第一個版本完全兼容。在 JavaScript 1.3 中, Netscape 增加了對 Unicode 標準的支持,并在保留 JavaScript 1.2 新增特性的同時實現了所有對象的平臺中立化。
在 Netscape 以 Mozilla 項目的名義開放其源代碼時,預期 JavaScript 1.4 將隨同 Netscape Navigator 5一道發布。然而,一個激進的決定,徹底重新設計 Netscape 代碼,打亂了原有計劃。后來, JavaScript 1.4只發布了針對 Netscape Enterprise Server 的服務器版,而沒有內置于 Web 瀏覽器中。
到了 2008 年,五大主流 Web 瀏覽器(IE、Firefox、Safari、Chrome 和 Opera)全部做到了與 ECMA-262兼容。 IE8 是第一個著手實現 ECMA-262 第 5 版的瀏覽器,并在 IE9 中提供了完整的支持。 Firefox 4 也緊隨其后做到兼容。下表列出了 ECMAScript 受主流 Web 瀏覽器支持的情況。
1.2.2 文檔對象模型( DOM)
文檔對象模型(DOM, Document Object Model)是針對 XML 但經過擴展用于 HTML 的應用程序編程接口(API, Application Programming Interface)。 DOM 把整個頁面映射為一個多層節點結構。 HTML或 XML 頁面中的每個組成部分都是某種類型的節點,這些節點又包含著不同類型的數據。看下面這個HTML 頁面:
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
在 DOM 中,這個頁面可以通過圖 1-2 所示的分層節點圖表示。
通過 DOM 創建的這個表示文檔的樹形圖,開發人員獲得了控制頁面內容和結構的主動權。借助DOM 提供的 API,開發人員可以輕松自如地刪除、添加、替換或修改任何節點。
1. 為什么要使用 DOM
在 Internet Explorer 4 和 Netscape Navigator 4 分別支持的不同形式的 DHTML(Dynamic HTML)基礎上,開發人員首次無需重新加載網頁,就可以修改其外觀和內容了。然而, DHTML 在給 Web 技術發展帶來巨大進步的同時,也帶來了巨大的問題。由于 Netscape 和微軟在開發 DHTML 方面各持己見,過去那個只編寫一個 HTML 頁面就能夠在任何瀏覽器中運行的時代結束了。
對開發人員而言,如果想繼續保持 Web 跨平臺的天性,就必須額外多做一些工作。而人們真正擔心的是,如果不對 Netscape 和微軟加以控制, Web 開發領域就會出現技術上兩強割據,瀏覽器互不兼容的局面。此時,負責制定 Web 通信標準的 W3C(World Wide Web Consortium,萬維網聯盟)開始著手規劃 DOM。
2. DOM 級別
DOM1 級(DOM Level 1)于 1998 年 10 月成為 W3C 的推薦標準。 DOM1 級由兩個模塊組成: DOM核心(DOM Core)和 DOM HTML。其中, DOM 核心規定的是如何映射基于 XML 的文檔結構,以便簡化對文檔中任意部分的訪問和操作。 DOM HTML 模塊則在 DOM 核心的基礎上加以擴展,添加了針對 HTML 的對象和方法。
請讀者注意, DOM 并不只是針對 JavaScript 的,很多別的語言也都實現了 DOM。不過,在 Web 瀏覽器中,基于 ECMAScript 實現的 DOM 的確已經成為 JavaScript 這門語言的一個重要組成部分。
如果說 DOM1 級的目標主要是映射文檔的結構,那么 DOM2 級的目標就要寬泛多了。 DOM2 級在原來 DOM 的基礎上又擴充了(DHTML 一直都支持的)鼠標和用戶界面事件、范圍、遍歷(迭代 DOM文檔的方法)等細分模塊,而且通過對象接口增加了對 CSS(Cascading Style Sheets,層疊樣式表)的支持。 DOM1 級中的 DOM 核心模塊也經過擴展開始支持 XML 命名空間。
DOM2 級引入了下列新模塊,也給出了眾多新類型和新接口的定義。
DOM 視圖(DOM Views):定義了跟蹤不同文檔(例如,應用 CSS 之前和之后的文檔)視圖的接口;
DOM 事件(DOM Events):定義了事件和事件處理的接口;
DOM 樣式(DOM Style):定義了基于 CSS 為元素應用樣式的接口;
DOM 遍歷和范圍(DOM Traversal and Range):定義了遍歷和操作文檔樹的接口。
DOM3 級則進一步擴展了 DOM,引入了以統一方式加載和保存文檔的方法——在 DOM 加載和保存(DOM Load and Save)模塊中定義;新增了驗證文檔的方法——在 DOM 驗證(DOM Validation)模塊中定義。 DOM3 級也對 DOM 核心進行了擴展,開始支持 XML 1.0 規范,涉及 XML Infoset、 XPath和 XML Base。
在閱讀 DOM 標準的時候,讀者可能會看到 DOM0 級(DOM Level 0)的字眼。實際上, DOM0 級標準是不存在的;所謂 DOM0 級只是 DOM 歷史坐標中的一個參照點而已。具體說來, DOM0 級指的是 Internet Explorer 4.0 和 Netscape Navigator 4.0 最初支持的 DHTML。
3. 其他 DOM 標準
除了 DOM 核心和 DOM HTML 接口之外,另外幾種語言還發布了只針對自己的 DOM 標準。下面列出的語言都是基于 XML 的,每種語言的 DOM 標準都添加了與特定語言相關的新方法和新接口:
SVG(Scalable Vector Graphic,可伸縮矢量圖) 1.0;
MathML(Mathematical Markup Language,數學標記語言) 1.0;
SMIL(Synchronized Multimedia Integration Language,同步多媒體集成語言)。
還有一些語言也開發了自己的 DOM 實現,例如 Mozilla 的 XUL (XML User Interface Language,XML用戶界面語言)。但是,只有上面列出的幾種語言是 W3C 的推薦標準。
4. Web 瀏覽器對 DOM 的支持
在 DOM 標準出現了一段時間之后, Web 瀏覽器才開始實現它。微軟在 IE5 中首次嘗試實現 DOM,但直到 IE5.5 才算是真正支持 DOM1 級。在隨后的 IE6 和 IE7 中,微軟都沒有引入新的 DOM 功能,而到了 IE8 才對以前 DOM 實現中的 bug 進行了修復。
Netscape 直到 Netscape 6(Mozilla 0.6.0)才開始支持 DOM。在 Netscape 7 之后, Mozilla 把開發重心轉向了 Firefox 瀏覽器。 Firefox 3 完全支持 DOM1 級,幾乎完全支持 DOM2 級,甚至還支持 DOM3 級的一部分。(Mozilla 開發團隊的目標是構建與標準 100%兼容的瀏覽器,而他們的努力也得到了回報。)
目前,支持 DOM 已經成為瀏覽器開發商的首要目標,主流瀏覽器每次發布新版本都會改進對 DOM的支持。下表列出了主流瀏覽器對 DOM 標準的支持情況。
1.2.3 瀏覽器對象模型( BOM)
Internet Explorer 3 和 Netscape Navigator 3 有一個共同的特色,那就是支持可以訪問和操作瀏覽器窗口的瀏覽器對象模型(BOM, Browser Object Model)。開發人員使用 BOM 可以控制瀏覽器顯示的頁面以外的部分。而 BOM 真正與眾不同的地方(也是經常會導致問題的地方),還是它作為 JavaScript 實現的一部分但卻沒有相關的標準。這個問題在 HTML5 中得到了解決, HTML5 致力于把很多 BOM 功能寫入正式規范。 HTML5 發布后,很多關于 BOM 的困惑煙消云散。從根本上講, BOM 只處理瀏覽器窗口和框架;但人們習慣上也把所有針對瀏覽器的 JavaScript 擴展算作 BOM 的一部分。下面就是一些這樣的擴展:
彈出新瀏覽器窗口的功能;
移動、縮放和關閉瀏覽器窗口的功能;
提供瀏覽器詳細信息的 navigator 對象;
提供瀏覽器所加載頁面的詳細信息的 location 對象;
提供用戶顯示器分辨率詳細信息的 screen 對象;
對 cookies 的支持;
像 XMLHttpRequest 和 IE 的 ActiveXObject 這樣的自定義對象。
由于沒有 BOM 標準可以遵循,因此每個瀏覽器都有自己的實現。雖然也存在一些事實標準,例如要有 window 對象和 navigator 對象等,但每個瀏覽器都會為這兩個對象乃至其他對象定義自己的屬性和方法。現在有了 HTML5, BOM 實現的細節有望朝著兼容性越來越高的方向發展。第 8 章將深入討論 BOM。