|
對(duì)于那些初學(xué)JavaScript、同時(shí)又正用它構(gòu)建大型應(yīng)用程序的開發(fā)者而言,必須面對(duì)的首要挑戰(zhàn)是,該如何組織代碼。盡管起初通過(guò)在
模塊模式(The Module Pattern)解決此問(wèn)題使用最為廣泛的方法是模塊模式(Module Pattern)。我嘗試在下面解釋一個(gè)基本示例,并談?wù)撍囊恍傩?。?duì)于各種不同方法更好的描述和夢(mèng)幻般的運(yùn)行,請(qǐng)參閱Ben Cherry的帖子——JavaScript Module Pattern: In-Depth(深入理解JavaScript模塊模式)。 (function(lab49) { 上面的示例中,我們只使用一些來(lái)自語(yǔ)言本身的基本功能,就創(chuàng)建了曾在C#和Java等語(yǔ)言中見過(guò)的類似結(jié)構(gòu)。 隔離(Isolation) 你會(huì)注意到這段代碼包在一個(gè)立即調(diào)用的函數(shù)里(查看最后一行)。在瀏覽器中,默認(rèn)情況下會(huì)在全局范圍(global scope)級(jí)別上對(duì)JavaScript文件進(jìn)行評(píng)估(evaluated),因此在我們?cè)谖募?nèi)聲明的任何內(nèi)容都是隨處可用的。想象一下,如果在lib1.js中有句 命名空間(Namespacing) 在最后一行中,你會(huì)發(fā)現(xiàn)我們要么把 首個(gè)包含進(jìn)來(lái)的文件會(huì)評(píng)估OR(邏輯或)語(yǔ)句,并發(fā)現(xiàn)左側(cè)表達(dá)式為undefined(未定義)。由于undefined是虛假值(falsely value),因此OR語(yǔ)句會(huì)繼續(xù)評(píng)估右側(cè)表達(dá)式,本例中是個(gè)空對(duì)象直接量。此OR語(yǔ)句實(shí)際上是個(gè)會(huì)返回評(píng)估結(jié)果的表達(dá)式,然后將結(jié)果賦給全局變量 現(xiàn)在,輪到下個(gè)文件來(lái)使用此模式了,它會(huì)獲得OR語(yǔ)句,并發(fā)現(xiàn) 這導(dǎo)致的結(jié)果是,首個(gè)包含進(jìn)來(lái)的文件會(huì)創(chuàng)建我們的 私有狀態(tài)(Private State)正如我們剛才所說(shuō),由于位于函數(shù)內(nèi)部,在其內(nèi)部聲明的一切內(nèi)容都是處于該函數(shù)的范圍內(nèi),而不是全局范圍。對(duì)于隔離我們的代碼這真太棒了,此外,它還有個(gè)影響是,沒(méi)有人能調(diào)用它。中看不中用。 剛剛我們還談到,我們創(chuàng)建了 在此函數(shù)內(nèi)聲明我們的值的另一結(jié)果是,如果某個(gè)值不是通過(guò)將其附加到我們的全局命名空間或者模塊外部的某物的方法來(lái)顯示公開的,那么外部代碼將無(wú)法碰到它。事實(shí)上,我們剛剛就創(chuàng)建了一些私有值。 CommonJS模塊(CommonJS Modules)CommonJS是一個(gè)主要由服務(wù)端JavaScript運(yùn)行庫(kù)(server-side JavaScript runtimes)作者組成的小組,他們一直致力于暴露及訪問(wèn)模塊的標(biāo)準(zhǔn)化工作(standardize exposing and accessing modules)。值得注意的是,盡管他們提議的模塊系統(tǒng)不是來(lái)自于創(chuàng)建JavaScript標(biāo)準(zhǔn)同一小組的一個(gè)標(biāo)準(zhǔn),因此它更多地成為JavaScript運(yùn)行庫(kù)作者之間的非正式約定(informal convention)。
該模塊規(guī)范(Modules specification)的核心可謂開門見山。模塊(Modules)在它們自己的上下文中進(jìn)行評(píng)估,并且擁有全局變量 // calculator.js 如果你曾經(jīng)玩過(guò)Node.js,那么你會(huì)發(fā)現(xiàn)上面的代碼很熟悉。這種用Node來(lái)實(shí)現(xiàn)CommonJS模塊的方式是出奇地簡(jiǎn)單,在node-inspector(一款Node調(diào)試器)中查看某個(gè)模塊時(shí)將顯示其包裝在某個(gè)函數(shù)內(nèi)部的內(nèi)容,此函數(shù)正是傳遞給 有幾個(gè)node項(xiàng)目(Stitch和Browserify),它們將CommonJS模塊帶進(jìn)了瀏覽器。服務(wù)器端組件將這些彼此獨(dú)立的模塊js文件塞進(jìn)一個(gè)單獨(dú)的js文件中,并在那些代碼外面包上生成的模塊包裝器(generated module wrapper)。 CommonJS主要設(shè)計(jì)用于服務(wù)端JavaScript運(yùn)行庫(kù),而且由于有幾個(gè)屬性使得它們很難在瀏覽器中進(jìn)行客戶端代碼的組織。
異步模塊定義(Asynchronous Module Definition)異步模塊定義(Asynchronous Module Definition,通常稱為AMD)已設(shè)計(jì)為適合于瀏覽器的模塊格式。它最初只是一個(gè)來(lái)自CommonJS小組的提議,但此后移到了GitHub上,而且現(xiàn)在伴有一個(gè)適用于模塊系統(tǒng)作者的測(cè)試套件,以便驗(yàn)證對(duì)于AMD API的遵從性(compliance)。 AMD的核心是 define('calculator', ['adder'], function(adder) { 由于此模塊的定義包在 為了與原本的CommonJS模塊提議保持兼容已作出重大努力。當(dāng)在模塊工廠函數(shù)中使用 看起來(lái)AMD正在成為頗受歡迎的組織客戶端JavaScript應(yīng)用程序的方式。無(wú)論是否通過(guò)如RequireJS或curl.js、或是像Dojo等最近已采用AMD的JavaScript應(yīng)用程序等模塊資源加載器來(lái)組織代碼。 這是否意味著JavaScript很爛?(Does this mean JavaScript sucks?)缺乏將代碼組織到模塊中的語(yǔ)言級(jí)別的結(jié)構(gòu)(language level constructs),這可能會(huì)讓來(lái)自于其他語(yǔ)言的開發(fā)者感覺(jué)很不爽。然而,正由于此缺陷才迫使JavaScript開發(fā)者想出他們自己的模塊構(gòu)造模式,我們已經(jīng)能夠隨著JavaScript應(yīng)用程序的發(fā)展進(jìn)行迭代和改進(jìn)。欲深入了解此主題請(qǐng)?jiān)L問(wèn)Tagneto的博客。 想象一下,即使這種功能類型(即Module)在10年前就已包括在語(yǔ)言中。那么他們也不可能想到在服務(wù)器上運(yùn)行大型JavaScript應(yīng)用程序、在瀏覽器中異步加載資源、或者像文本模板(text templates)(那些載入器就像RequireJS所做的一樣)那樣包含資源等諸如此類的需求。 正在考慮將模塊(Modules)作為Harmony/ECMAScript 6的語(yǔ)言級(jí)別功能。這多虧了模塊系統(tǒng)作者們的思想和過(guò)去幾年的辛勤工作,很可能我們最終得到的語(yǔ)言會(huì)適用于構(gòu)建現(xiàn)代JavaScript應(yīng)用程序。 |
|
|
來(lái)自: 旭龍 > 《程序設(shè)計(jì)》