官术网_书友最值得收藏!

1.7 JavaScript的應(yīng)用環(huán)境

在此前的內(nèi)容中,我們討論的都是JavaScript語(yǔ)言及其規(guī)范,而并非該語(yǔ)言的應(yīng)用環(huán)境。在大多數(shù)人看來(lái),JavaScript的應(yīng)用環(huán)境就是Web瀏覽器,這也的確是該語(yǔ)言最早的設(shè)計(jì)目標(biāo)。然而從很早開(kāi)始,JavaScript語(yǔ)言就已經(jīng)在其他的復(fù)雜應(yīng)用環(huán)境中使用,并受這些應(yīng)用環(huán)境的影響而發(fā)展出新的語(yǔ)言特性了。正是這些復(fù)雜的應(yīng)用環(huán)境推動(dòng)了JavaScript 2的到來(lái)。按照ECMA Edition 4標(biāo)準(zhǔn)規(guī)范小組的說(shuō)明,ECMA Edition 4主要面對(duì)的問(wèn)題,就在于JavaScript 1.x沒(méi)有足夠的抽象能力和語(yǔ)言機(jī)制,因而難于勝任大型編程系統(tǒng)環(huán)境下的開(kāi)發(fā)。不過(guò)ECMA Edition 4版本由于定義時(shí)過(guò)于激進(jìn)而未能得到開(kāi)發(fā)界的認(rèn)可,一直到ECMA Edition 6之后,才基本實(shí)現(xiàn)了上述目標(biāo)。

JavaScript的應(yīng)用環(huán)境,主要由宿主環(huán)境與運(yùn)行期環(huán)境構(gòu)成。其中,宿主環(huán)境是指外殼程序(shell)和Web瀏覽器等,而運(yùn)行期環(huán)境則是由JavaScript引擎內(nèi)建的。圖1-9說(shuō)明了由宿主環(huán)境和運(yùn)行期環(huán)境共同構(gòu)建的對(duì)象編程系統(tǒng)的基本結(jié)構(gòu)。

圖1-9 由宿主環(huán)境與運(yùn)行期環(huán)境構(gòu)成的應(yīng)用環(huán)境

1.7.1 宿主環(huán)境

JavaScript是一門(mén)設(shè)計(jì)得相對(duì)“原始”的語(yǔ)言,它被創(chuàng)建時(shí)的最初目標(biāo)僅僅是為Netscape提供一門(mén)在瀏覽器與服務(wù)器間都能統(tǒng)一使用的開(kāi)發(fā)語(yǔ)言。簡(jiǎn)單地說(shuō),它原來(lái)的設(shè)計(jì)目標(biāo)是想讓B/S架構(gòu)兩端的開(kāi)發(fā)人員用起來(lái)都能舒服一些。這意味著最初的設(shè)計(jì)者希望JavaScript語(yǔ)言是跨平臺(tái)的,能夠提供“端到端(side to side)”的整體解決方案。

然而事實(shí)上這非常難做到,因?yàn)椴煌钠脚_(tái)提供的“可執(zhí)行環(huán)境”不同。而宿主環(huán)境(host environment)就是為了隔離代碼、語(yǔ)言與具體的平臺(tái)而提出的一種設(shè)計(jì)。一方面,我們不能讓瀏覽器中擁有一個(gè)巨大無(wú)比的運(yùn)行期環(huán)境(例如像虛擬機(jī)那么大);另一方面,服務(wù)器端又需要一個(gè)較強(qiáng)大的環(huán)境,因此JavaScript就被設(shè)計(jì)成了需要“宿主環(huán)境”的語(yǔ)言。虛擬機(jī)(Virtual Machine)是另一種隔離語(yǔ)言與平臺(tái)環(huán)境的手段,Java與.NET Framework都以虛擬機(jī)的方式提供運(yùn)行環(huán)境。在這種方案中,宿主的作用是提供混合語(yǔ)言編程的能力和跨語(yǔ)言的對(duì)象系統(tǒng),而虛擬機(jī)則著眼于跨平臺(tái)的、語(yǔ)言無(wú)關(guān)的虛擬執(zhí)行環(huán)境。

ECMAScript規(guī)范并沒(méi)有對(duì)宿主環(huán)境提出明確的定義。比如,它沒(méi)有提出標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出(stdin、stdout)需要確切地實(shí)現(xiàn)在哪個(gè)對(duì)象中。為了彌補(bǔ)這個(gè)問(wèn)題,RWC在WebAPI規(guī)范中首先就提出了“需要一個(gè)window對(duì)象”的瀏覽器環(huán)境。這意味著在RWC或者瀏覽器端,是以window對(duì)象及其中的Document對(duì)象來(lái)提供輸入輸出的。

但這仍然不是全部的真相。因?yàn)椤癛WC規(guī)范下的宿主環(huán)境”,并不等同于“JavaScript規(guī)范下的宿主環(huán)境”。本書(shū)也并不打算討論與特定瀏覽器相關(guān)的細(xì)節(jié)問(wèn)題,因此我們采用在多數(shù)宿主程序中的實(shí)現(xiàn):使用全局對(duì)象console來(lái)提供輸入輸出,本書(shū)第1版和第2版采用Web瀏覽器上的慣例:使用alert()來(lái)顯示消息。對(duì)于某些引擎來(lái)說(shuō),無(wú)論是alert()方法還是console對(duì)象,都可能是未實(shí)現(xiàn)的,例如,WScript就需要使用WScript.Echo()來(lái)輸出,而ESHOST則約定使用print()函數(shù)。如表1-2所示。

表1-2 本書(shū)對(duì)宿主環(huán)境在全局方法上的簡(jiǎn)單設(shè)定

1.7.2 外殼程序

外殼程序(shell)是宿主的一種。

不過(guò)在其他的一些文檔中并不這樣解釋?zhuān)窃噲D將宿主與外殼分別看待。其中的原因在于將“跨語(yǔ)言宿主”與“應(yīng)用宿主”混為一談。

在Windows環(huán)境中,微軟提供的WSH(Windows Script Host)是一種跨語(yǔ)言宿主,在該宿主環(huán)境中提供一個(gè)公共的對(duì)象系統(tǒng),并提供裝載不同的編程語(yǔ)言引擎的能力。如此一來(lái),WSH可以讓多種語(yǔ)言使用同一套對(duì)象—這些對(duì)象由一些COM組件來(lái)實(shí)現(xiàn)并注冊(cè)到Windows系統(tǒng)中。所以我們?cè)贗E瀏覽器中既可以用VBScript操作網(wǎng)頁(yè)中的對(duì)象,也可以用JScript來(lái)操作。基本上來(lái)講,IE瀏覽器采用的是與WSH完全相同的宿主實(shí)現(xiàn)技術(shù)。

多數(shù)JavaScript引擎會(huì)提供一個(gè)用于演示的外殼程序。該外殼程序通過(guò)一種命令行交互式界面來(lái)展示引擎的能力—在UNIX/Linux系統(tǒng)中編程的開(kāi)發(fā)人員會(huì)非常習(xí)慣這種環(huán)境,而在Windows中編程的開(kāi)發(fā)人員則不然。在這種環(huán)境下,可以像調(diào)試器中的單步跟蹤一樣,展示出許多引擎內(nèi)部的細(xì)節(jié)。圖1-10所示的是SpiderMonkey JavaScript隨引擎同時(shí)發(fā)布的一個(gè)外殼程序,它就是(該腳本引擎的)一個(gè)應(yīng)用宿主。

如同引擎提供的這種外殼程序,我們一般所見(jiàn)到的shell是指一種簡(jiǎn)單的應(yīng)用宿主,它只負(fù)責(zé)提供一個(gè)宿主應(yīng)用環(huán)境:包括對(duì)象和與對(duì)象運(yùn)行相關(guān)的操作系統(tǒng)進(jìn)程。但是在另外一些情況下,“外殼(而不是外殼程序)”和“宿主”也被賦予一些其他的含義。例如,在WSH中,“宿主”是指整個(gè)的宿主環(huán)境和提供該環(huán)境的技術(shù),而“shell”則是其中的一個(gè)可編程對(duì)象(WScript.WshShell)—封裝了Windows系統(tǒng)的功能(例如注冊(cè)表、文件系統(tǒng)等)的一個(gè)“外殼對(duì)象”,而非“外殼程序”。

而Node.js的情況比這些都要復(fù)雜。Node.js中的默認(rèn)JavaScript引擎是V8,這個(gè)腳本引擎可以連接到node主進(jìn)程的內(nèi)部,或者單獨(dú)以DLL(動(dòng)態(tài)鏈接庫(kù))的形式提供。所謂node主進(jìn)程,就是一個(gè)宿主,然而這個(gè)宿主如果以交互形式運(yùn)行,那么它又是一個(gè)傳統(tǒng)意義上的外殼程序。在后者這種情況下,開(kāi)發(fā)人員可以在命令行交互式界面上進(jìn)行測(cè)試、調(diào)試等,由其(動(dòng)態(tài)加載的)內(nèi)核模塊repl來(lái)提供支持。在這兩種模式下,Node.js都以全局的process對(duì)象來(lái)提供對(duì)宿主的訪(fǎng)問(wèn),例如可以通過(guò)process.moduleLoadList查看當(dāng)前裝載的模塊列表。

圖1-10 SpiderMonkey JavaScript提供的外殼程序

討論腳本引擎本身時(shí),我們并不強(qiáng)調(diào)宿主環(huán)境的形式是WSH這種“使用跨語(yǔ)言宿主技術(shù)構(gòu)建的腳本應(yīng)用環(huán)境”,還是SpiderMonkey JavaScript或Node.js所提供的這種“交互式命令行程序”。我們只強(qiáng)調(diào):腳本引擎必須運(yùn)行在一個(gè)宿主之中,并由該宿主創(chuàng)建和維護(hù)腳本引擎實(shí)例的“運(yùn)行期環(huán)境(runtime)”。

1.7.3 運(yùn)行期環(huán)境

不同的書(shū)籍對(duì)JavaScript運(yùn)行期(runtime)環(huán)境的闡釋是不一樣的。例如,在《JavaScript權(quán)威指南》中,它由“JavaScript內(nèi)核(Core)”和“客戶(hù)端(Client)JavaScript”兩部分構(gòu)成;而在《JavaScript高級(jí)程序設(shè)計(jì)》中,它被描述成由“核心(ECMAScript)”“文檔對(duì)象模型(DOM)”“瀏覽器對(duì)象模型(BOM)”三個(gè)部分組成(見(jiàn)圖1-11)。

圖1-11 對(duì)“運(yùn)行期環(huán)境”的不同解釋

本書(shū)是從引擎的角度討論JavaScript的,因此在本書(shū)看來(lái),與瀏覽器相關(guān)的內(nèi)容都屬于“應(yīng)用環(huán)境”:屬于宿主環(huán)境或?qū)儆谟脩?hù)編程環(huán)境。本小節(jié)開(kāi)始位置的圖1-9表達(dá)了這種關(guān)系。在這樣的關(guān)系中,運(yùn)行期環(huán)境是由宿主通過(guò)腳本引擎(JavaScript Engines)創(chuàng)建的。一些常見(jiàn)的JavaScript Engines包括Windows和Internet Explorer中的jscript.dll,以及在Mozilla Firefox中的js3250.dll等。我們絕大多數(shù)的討論會(huì)面向由這樣的腳本引擎決定的、具體的運(yùn)行期環(huán)境。圖1-12說(shuō)明了應(yīng)用程序—宿主在這里可以看成一個(gè)應(yīng)用程序—如何創(chuàng)建運(yùn)行期環(huán)境。引用自JavaScript C Engine s Guide。

圖1-12 應(yīng)用(宿主)通過(guò)引擎創(chuàng)建“運(yùn)行期環(huán)境”的過(guò)程

因此,在本書(shū)中講述的運(yùn)行期環(huán)境特指由引擎創(chuàng)建的初始應(yīng)用環(huán)境。主要包括:

■ 一個(gè)對(duì)宿主的約定。

■ 一個(gè)引擎內(nèi)核。

■ 一組對(duì)象和API。

■ 一些其他的規(guī)范。

我們這樣解釋運(yùn)行期環(huán)境的特點(diǎn),而并不強(qiáng)調(diào)(或包括)在應(yīng)用、宿主或用戶(hù)代碼混雜作用的、運(yùn)行過(guò)程中的應(yīng)用環(huán)境,就是要將討論聚焦于引擎自身的能力。不過(guò)即使如此,不同的JavaScript腳本引擎所提供的語(yǔ)言特性也并不一致。因此,在本書(shū)中若非特別說(shuō)明,JavaScript是指一種通用的、跨平臺(tái)的和跨環(huán)境的語(yǔ)言,并不特指某種特定的宿主環(huán)境或者運(yùn)行環(huán)境。也就是說(shuō),它是指ECMAScript-262所描述的語(yǔ)言規(guī)范。

1.7.4 兼容環(huán)境下的測(cè)試

本書(shū)撰寫(xiě)的代碼主要使用Node.js 4.x來(lái)進(jìn)行測(cè)試,但所有代碼全部經(jīng)過(guò)兼容性檢查,以確保它們?cè)贜ode.js 4.x之后的版本中表現(xiàn)一致(或?qū)τ胁町惖膬?nèi)容做出明確解釋?zhuān)?/p>

本書(shū)所述的兼容環(huán)境包括Chakra、JavaScriptCore、Node.js、SpiderMonkey、V8和xs。本書(shū)使用ESHOST和JSVUeshost是由bterlson發(fā)布的一個(gè)開(kāi)源產(chǎn)品,用于在多個(gè)JavaScript引擎之上構(gòu)建相同的宿主環(huán)境。JSVU是由Google Labs發(fā)布的,用于管理和更新不同的JavaScript引擎。來(lái)構(gòu)建測(cè)試環(huán)境,并確保所有示例得到完整測(cè)試。讀者可以嘗試通過(guò)如下方式構(gòu)建相應(yīng)的測(cè)試環(huán)境。

需要留意的是,默認(rèn)情況下執(zhí)行jsvu總是更新全部最新版本的JavaScript引擎。你可以用如下命令行來(lái)切換不同的版本,或指定JSVU或ESHOST有選擇地管理哪些引擎。例如:

本書(shū)將通過(guò)開(kāi)源項(xiàng)目提供全部章節(jié)的示例和相關(guān)代碼請(qǐng)關(guān)注我的Git倉(cāng)庫(kù)(aimingoo/js-green-book-3)。,讀者可以參考閱讀。

主站蜘蛛池模板: 阜平县| 阳春市| 罗山县| 长沙县| 望奎县| 景洪市| 克拉玛依市| 喀什市| 长寿区| 台南县| 衡阳市| 拜城县| 吉木乃县| 汽车| 上栗县| 鹤壁市| 万全县| 天门市| 湟中县| 苍山县| 定西市| 彝良县| 宽城| 曲周县| 龙胜| 老河口市| 兴城市| 鸡西市| 甘洛县| 三台县| 克山县| 大庆市| 工布江达县| 锦屏县| 临安市| 怀柔区| 穆棱市| 夹江县| 沙河市| 双牌县| 锡林浩特市|