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