瞭解Javascript的模組化開發_javascript技巧

來源:互聯網
上載者:User

小A是某個創業團隊的前端工程師,負責編寫項目的Javascript程式。

全域變數衝突

根據自己的經驗,小A先把一些常用的功能抽出來,寫成函數放到一個公用檔案base.js中:

複製代碼 代碼如下:

var _ = {
    $: function(id) { return document.getElementById(id); },
    getCookie: function(key) { ... },
    setCookie: function(key, value) { ... }
};

小A把這些函數都放在_對象內,以防過多的全域變數造成衝突。他告訴團隊的其他成員,如果誰想使用這些函數,只要引入base.js就可以了。

小C是小A的同事,他向小A反映:自己的頁面引入了一個叫做underscore.js的類庫,而且,這個類庫也會佔用_這個全域變數,這樣一來就會跟base.js中的_衝突了。小A心想,underscore.js是第三方類庫,估計不好改,但是base.js已經在很多頁面鋪開,不可能改。最後小A只好無奈地把underscore.js佔用的全域變數改了。

此時,小A發現,把函數都放在一個名字空間內,可以減少全域變數衝突的機率,卻沒有解決全域變數衝突這個問題。

依賴

隨著業務的發展,小A又編寫了一系列的函數庫和UI組件,比方說標籤切換組件tabs.js,此組件需調用base.js以及util.js中的函數。

有一天,新同事小D跟小A反映,自己已經在頁面中引用了tabs.js,功能卻不正常。小A一看就發現問題了,原來小D不知道tabs.js依賴於base.js以及util.js,他並沒有添加這兩個檔案的引用。於是,他馬上進行修改:

複製代碼 代碼如下:

<script src="tabs.js"></script>
<script src="base.js"></script>
<script src="util.js"></script>

然而,功能還是不正常,此時小A教訓小D說:“都說是依賴,那被依賴方肯定要放在依賴方之前啊”。原來小D把base.js和util.js放到tabs.js之後了。

小A心想,他是作者,自然知道組件的依賴情況,但是別人就難說了,特別是新人。

過了一段時間,小A給標籤切換組件增加了功能,為了實現這個功能,tabs.js還需要調用ui.js中的函數。這時,小A發現了一個嚴重的問題,他需要在所有調用了tabs.js的頁面上增加ui.js的引用!!!

又過了一段時間,小A最佳化了tabs.js,這個組件已經不再依賴於util.js,所以他在所有用到tabs.js的頁面中移除了util.js的引用,以提高效能。他這一修改,出大事了,測試組MM告訴他,有些頁面不正常了。小A一看,恍然大悟,原來某些頁面的其他功能用到了util.js中的函數,他把這個檔案的引用去掉導致出錯了。為了保證功能正常,他又把代碼恢複了。

小A又想,有沒有辦法在修改依賴的同時不用逐一修改頁面,也不影響其他功能呢?

模組化

小A逛互連網的時候,無意中發現了一種新奇的模組化編碼方式,可以把它之前遇到的問題全部解決。

在模組化編程方式下,每個檔案都是一個模組。每個模組都由一個名為define的函數建立。例如,把base.js改造成一個模組後,代碼會變成這樣:

複製代碼 代碼如下:

define(function(require, exports, module) {
    exports.$ = function(id) { return document.getElementById(id); };
    exports.getCookie = function(key) { ... };
    exports.setCookie = function(key, value) { ... };
});

base.js向外提供的介面都被添加到exports這個對象。而exports是一個局部變數,整個模組的代碼都沒有佔用半個全域變數。

那如何調用某個模組提供的介面呢?以tabs.js為例,它要依賴於base.js和util.js:

複製代碼 代碼如下:

define(function(require, exports, module) {
    var _ = require('base.js'), util = require('util.js');
    var div_tabs = _.$('tabs');
    // .... 其他代碼
});

一個模組可以通過局部函數require擷取其他模組的介面。此時,變數_和util都是局部變數,並且,變數名完全是受開發人員控制的,如果你不喜歡_,那也可以用base:
複製代碼 代碼如下:

define(function(require, exports, module) {
    var base = require('base.js'), util = require('util.js');
    var div_tabs = base.$('tabs');
    // .... 其他代碼
});

一旦要移除util.js、添加ui.js,那隻要修改tabs.js就可以了:
複製代碼 代碼如下:

define(function(require, exports, module) {
    var base = require('base.js'), ui = require('ui.js');
    var div_tabs = base.$('tabs');
    // .... 其他代碼
});

載入器

由於缺乏瀏覽器的原生支援,如果我們要用模組化的方式編碼,就必須藉助於一個叫做載入器(loader)的東西。

目前載入器的實現有很多,比如require.js、seajs。而JRaiser類庫也有自己的載入器。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.