- JavaScript語言精髓與編程實踐
- 周愛民
- 2591字
- 2018-12-30 08:46:39
1.6 JavaScript的應用環境
在此前的內容中,我討論的都是JavaScript語言及其規范,而并非該語言的應用環境。在大多數人看來,JavaScript的應用環境都是Web瀏覽器,這也的確是該語言最早的設計目標。然而從很早開始,JavaScript語言就已經在其他的復雜應用環境中使用,并受這些應用環境的影響而發展出新的語言特性了。
JavaScript的應用環境,主要由宿主環境(host environment)與運行期環境構成。其中,宿主環境是指外殼程序(Shell)和Web瀏覽器等,而運行期環境則是由JavaScript引擎內建的。圖1-9是由它們共同構建的對象編程系統的基本結構。

圖1-9 由宿主與運行期構成的應用環境
1.6.1 宿主環境
JavaScript是一門設計得相對“原始”一點點的語言,它被創生時的最初目標僅僅是為Netscape提供一個在瀏覽器與服務器間都能統一使用的開發語言。簡單地說,它原來是想讓B/S架構下的開發人員用起來都舒服那么一點點的。這意味著最初的設計者希望JavaScript語言是跨平臺的,能夠提供“端到端(side to side)”的整體解決方案。
然而,事實上這非常難做到,因為不同的平臺提供的“可執行環境”不同。而宿主環境就是為了隔離代碼、語言與具體的平臺而提出的一個設計。一方面我們不能讓瀏覽器上擁有一個巨大無比的運行期環境(例如像虛擬機那么大),另一方面服務器端又需要一個較強大的環境,因此JavaScript就被設計成了需要“宿主環境”的語言。
ECMAScript規范并沒有對宿主環境提出明確的定義。比如說,它沒有提出標準輸入輸出(stdin、stdout)需要確切地實現在哪個對象中。為了彌補這個問題,RWC在WebAPIs規范中首先就提出了“需要一個window對象”的瀏覽器環境。這意味著在RWC或者瀏覽器端,是以window對象及其中的Document對象來提供輸入輸出的。
但這仍然不是全部的真相。因為“RWC規范下的宿主環境”,并不等同于“JavaScript規范下的宿主環境”。本書并不打算討論與特定瀏覽器相關的細節問題,因此我們事實上在說的是JavaScript的一個公共語言環境,或者說公共的宿主環境的定義。作為程序運行過程中對輸入輸出的基本要求,本書設定宿主環境在全局應當支持如表1-3所示的方法。
表1-3 本書對宿主環境在全局方法上的簡單設定

*注1:write()與writeln()在瀏覽器中是Document對象的方法。為遵循這一慣例,在本書的所有測試范例中并不直接使用這兩個方法。但這里保留了它們,以描述宿主環境的標準輸入輸出。
對于不同的宿主來說,這些方法依賴于不同的對象層次的“頂層對象(或全局對象)”。例如瀏覽器宿主依賴于window對象,而WSH宿主則依賴于WScript對象。但在本書中,調用這些方法時將略去這個對象。因此,至少它看起來很像是Global對象上的方法(事實上,大多數的宿主默認“頂層對象”不需要使用全名的約定)。
下面的代碼說明在具體的宿主環境中如何實現本書所適用的alert()方法。例如:
// 示例1: .NET Framework中的JScript 8.0, (當前的)頂層對象取決于import語句 // (注: JScript.NET中的腳本需要編譯執行) import System.Windows.Forms; function alert(sMessage) { MessageBox.Show(sMessage); } alert(' Hello, World! ' ) // 示例2:瀏覽器環境中使用的頂層對象是window alert(' Hello, World! ' ); // 示例3:WSH環境中使用的頂層對象是WScript,但必須使用全名 function alert(sMessage) { WScript.Echo(sMessage); } alert(' Hello, World! ' );
1.6.2 外殼程序
外殼程序(shell)是宿主的一種。不過在其他一些文檔中并不這樣解釋,而是試圖將宿主與外殼分別看待。這其中的原因在于將“跨語言宿主”與“應用宿主”混為一談。
Windows環境中,微軟提供的WSH(Windows Script Host)是一種跨語言宿主,在該宿主環境中提供一個公共的對象系統,并提供裝載不同的編程語言引擎的能力。如此一來,WSH可以讓多個語言使用同一套對象——這些對象由一些COM組件來實現并注冊到Windows系統中。所以,我們在IE瀏覽器中看到,既可以用VBScript操作網頁中的對象,也可以用JScript來操作它。基本上來講,IE瀏覽器采用的是與WSH完全相同的宿主實現技術。
多數JavaScript引擎會提供一個用于演示的外殼程序。該外殼程序通過一種命令行交互式界面來展示引擎的能力,在UNIX/Linux系統中編程的開發人員會非常習慣這種環境,而在Windows中編程的開發人員則不然。在這種環境下,可以像調試器中的單步跟蹤一樣,展示出許多引擎內部的細節。圖1-10是SpiderMonkey JavaScript隨引擎同時發布一個外殼程序,它就是(該腳本引擎的)一個應用宿主。
如同引擎提供的這種外殼程序一樣,我們一般所見的Shell是指一種簡單的應用宿主,它只負責提供一個宿主應用環境:包括對象和與對象運行相關的操作系統進程。但是在另外一些情況下,“外殼(而不是外殼程序)”和“宿主”也被賦予一些其他的含義。例如在WSH中,“宿主”是指整個宿主環境和提供該環境的技術,而Shell則是其中的一個可編程對象(WScript.WshShell)——封裝了Windows系統的功能(如注冊表、文件系統等)的一個“外殼對象”,而非“外殼程序”。

圖1-10 SpiderMonkey JavaScript提供的外殼程序
討論腳本引擎本身時,我們并不強調宿主環境的形式是WSH這種“使用跨語言宿主技術構建的腳本應用環境”,還是SpiderMonkey JavaScript所提供的這種“交互式命令行程序”。我們只強調:腳本引擎必須運行在一個宿主之中,并由該宿主創建和維護腳本引擎實例的“運行期環境(runtime)”。
1.6.3 運行期環境
在不同的書籍中對JavaScript運行期環境的闡釋是不一致的。例如在《JavaScript權威指南》中,它由JavaScript內核(Core)和客戶端(Client)JavaScript兩部分構成;而在《JavaScript高級程序設計》中,它被描述成由核心(ECMAScript)、文檔對象模型(DOM)、瀏覽器對象模型(BOM)三個部分組成,如圖1-11所示)。

圖1-11 對“運行期環境”的不同解釋
本書是從引擎的角度討論JavaScript的,因此在本書看來,與瀏覽器相關的內容都屬于“應用環境”:屬于宿主環境或屬于用戶編程環境。圖1-9由宿主與運行期構成的應用環境”表達了這種關系。在這樣的關系中,運行期環境是由宿主通過腳本引擎(JavaScript Engines)創建的。圖1-12說明應用程序,是宿主在這里可以看成一個應用程序,是如何創建運行期環境
的。

圖1-12 應用(宿主)通過引擎創建“運行期環境”的過程
這相當于是說,在本書中講述的運行期環境,是特指由引擎創建的初始應用環境。這樣解釋運行期環境的特點,而并不強調(或包括)在應用、宿主或用戶代碼混雜作用的、運行過程中的應用環境。在初始狀態下的運行期環境主要包括:
█ 一個對宿主的約定。
█ 一個引擎內核。
█ 一組對象和API。
█ 一些其他的規范。
換而言之,這是指一個引擎自身的能力。不過即使如此,不同的JavaScript腳本引擎所提供的語言特性也并不一致。因此,在本書中若非特別說明,JavaScript是指一種通用的、跨平臺和跨環境的語言,并不特指某種特定的宿主環境或者運行環境。也就是說,它是指ECMAScript 262所描述的語言規范。目前最常見的實現ECMAScript Ed3或JavaScript 1.5以上版本規范的引擎包括如表1-4所示的幾種。
表1-4 最常見的一些JavaScript引擎(部分)

*注1:Brendan Eich為驗證JavaScript語言的自實現能力而寫的一套代碼,被稱為“JS implemented in JS”。有許多項目基于該代碼進行擴展,例如NarrativEJS基于該項目實現了JavaScript上的解釋器、編譯器和擴展語法。
- Web程序設計及應用
- Learning Scala Programming
- LabVIEW Graphical Programming Cookbook
- Python Geospatial Development(Second Edition)
- Instant RubyMotion App Development
- C++面向對象程序設計習題解答與上機指導(第三版)
- MATLAB 2020從入門到精通
- Hands-On Neural Network Programming with C#
- Orchestrating Docker
- 大學計算機基礎實驗指導
- Exploring SE for Android
- Sails.js Essentials
- 分布式架構原理與實踐
- IBM RUP參考與認證指南
- HikariCP數據庫連接池實戰