JavaScript模組化開發的那些事
模組化開發在程式設計開發中是一個非常重要的概念,一個優秀的模組化專案的後期維護成本可以大大降低。本文主要介紹了JavaScript模組化開發的那些事,文中通過一個小故事比較直觀地闡述了模組化開發的過程。
小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類庫也有自己的載入器。
相關文章
- Node那些事之模組化
- Javascript模組化開發基礎JavaScript
- 詳解JavaScript模組化開發JavaScript
- 模組化JavaScript元件開發指南JavaScript元件
- 敏捷開發的那些事敏捷
- JavaScript那些事JavaScript
- Clojure 開發那些事
- JavaScript模組化開發一瞥JavaScript
- JavaScript模組化開發的演進歷程JavaScript
- javascript中this那些事JavaScript
- JavaScript閉包的那些事~JavaScript
- JavaScript 陣列的那些事JavaScript陣列
- 為什麼JavaScript需要模組化開發?JavaScript
- iOS開發那些事-效能優化–autorelease的使用問題iOS優化
- 淺談Blazor開發的那些事Blazor
- JavaScript進階【一】JavaScript模組化開發的基礎知識JavaScript
- 遊戲開發過程中需求變化那些事遊戲開發
- JavaScript 閉包那些事JavaScript
- 概覽【JavaScript那些事】JavaScript
- web前端開發框架那些事Web前端框架
- 開發更好用的 JavaScript 模組JavaScript
- JavaScript 中 setTimeout 的那些事兒JavaScript
- javascript模組化發展歷程JavaScript
- 區塊鏈開發:公鏈開發那些事兒區塊鏈
- app 效能優化的那些事APP優化
- JavaScript非同步處理的那些事兒JavaScript非同步
- 遊戲開發專案管理那些事遊戲開發專案管理
- Js模組化開發的理解JS
- JavaScript 中的模組化JavaScript
- 模組化開發(二)
- 前端模組化開發前端
- Laravel 模組化開發Laravel
- JavaScript模組化JavaScript
- 關於Javascript中的”use strict”的那些事JavaScript
- app 效能優化的那些事(二)APP優化
- ABAP開發環境語法高亮的那些事兒開發環境
- 元件化開發和模組化開發概念辨析元件化
- JavaScript和Objective-C互動的那些事JavaScriptObject