JavaScript模塊化開發的那些事

模塊化開發在編程開發中是一個很是重要的概念,一個優秀的模塊化項目的後期維護成本能夠大大下降。本文主要介紹JavaScript模塊化開發的那些事,文中經過一個小故事比較直觀地闡述了模塊化開發的過程。javascript

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

全局變量衝突

根據本身的經驗,小A先把一些經常使用的功能抽出來,寫成函數放到一個公用文件base.js中:前端

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

小A把這些函數都放在_對象內,以防過多的全局變量形成衝突。他告訴團隊的其餘成員,若是誰想使用這些函數,只要引入base.js就能夠了。java

小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類庫也有本身的加載器。

原文出處:JavaScript模塊化開發的那些事

相關文章
相關標籤/搜索