為什么要使用模塊化
網(wǎng)站越來越復(fù)雜掉缺,js代碼、js文件也越來越多
1.命名沖突
2.文件依賴問題
- 程序中的模塊化
- 開發(fā)效率高 一次編寫多次使用
- 方便維護(hù)了(維護(hù)的成本更低)模塊之間有高耦合低內(nèi)聚的特點(diǎn)
對象封裝
- 用命名空間的方式進(jìn)行封裝
- 先約定命名的規(guī)范的形式
- 對象里面的屬性和方法很容易被修改掉戈擒,很不安全
劃分私有空間
-通過匿名函數(shù)自執(zhí)行的方法封裝模塊眶明,
-可以保護(hù)私有變量和方法
模塊的維護(hù)擴(kuò)展
- 開閉原則,對修改關(guān)閉筐高,對擴(kuò)展開放搜囱。
- 增加了代碼的健壯性和容錯(cuò)性
模塊的第三方依賴
- 模塊職責(zé)唯一性
- 把依賴的模塊丑瞧,通過依賴注入的形式,在你的參數(shù)上進(jìn)行體現(xiàn)蜀肘。
總結(jié)
- 最大的問題绊汹,規(guī)范的問題
- 如果在多人協(xié)作開發(fā)過程中,會(huì)有很大的問題
- 多人協(xié)作開發(fā)過程中:代碼的風(fēng)格一定要統(tǒng)一
JavaScript模塊化實(shí)現(xiàn)的三種技術(shù)規(guī)范
http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html 阮一峰博客
實(shí)際上扮宠,這三種第三方框架西乖,目前已經(jīng)很少用了,seajs最近一次更新是在2014年了坛增。因?yàn)镴S現(xiàn)在的語法越來越完善获雕,正在向強(qiáng)語言進(jìn)化,強(qiáng)語言本身就自帶模塊化收捣。
AMD
AMD是"Asynchronous Module Definition"的縮寫典鸡,意思就是"異步模塊定義"。它采用異步方式加載模塊坏晦,模塊的加載不影響它后面語句的運(yùn)行。所有依賴這個(gè)模塊的語句嫁乘,都定義在一個(gè)回調(diào)函數(shù)中昆婿,等到加載完成之后,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行蜓斧。
AMD規(guī)范其實(shí)只有一個(gè)主要接口 define(id,dependencies,factory)仓蛆,它要在聲明模塊的時(shí)候指定所有的依賴dependencies,并且還要當(dāng)做形參傳到factory中挎春,對于依賴的模塊提前執(zhí)行看疙,依賴前置
//定義模塊
define("module", ["dep1", "dep2"], function(d1, d2) {
return someExportedValue;
});
//引入模塊
require(["module", "../file"], function(module, file) {
});
優(yōu)點(diǎn):
適合在瀏覽器環(huán)境異步加載
并行加載多個(gè)模塊
缺點(diǎn):
提高開發(fā)成本,代碼閱讀和書寫比較困難
不符合通用的模塊思維方式直奋,是一種妥協(xié)的實(shí)現(xiàn)
實(shí)現(xiàn):
require.js
CMD
CMD規(guī)范和AMD相似能庆,盡量保持簡單,并且與CommonJS和NodeJS的Modules規(guī)范保持了很大的兼容性脚线。
//定義模塊
define(function(require, exports, module) {
var $ = require('jquery');
var Spinning = require('./spinning');
exports.doSomething = ...
module.exports = ...
})
//導(dǎo)入模塊
//第一參數(shù)是入口模塊的路徑
//第二個(gè)函數(shù)是回調(diào)函數(shù)
seajs.use('路徑',function(回調(diào)對象){
//此回調(diào)對象就是moudle.exports對象搁胆。我們可以使用定義模塊中,module.exports對象所有的屬性與方法
});
優(yōu)點(diǎn):
依賴就近邮绿,延遲執(zhí)行
很容易在node中運(yùn)行
缺點(diǎn):
依賴SPM打包渠旁,模塊的加載邏輯偏重
實(shí)現(xiàn): SeaJS
SeaJS路徑配置
//seajs所在的路徑為默認(rèn)根目錄
seajs.config({
//配置根目錄
base: “../sea-modules/”,
//別名
alias : {
“jquery”: “jquery/jquery/1.10.1/jquery.js(路徑)” //方便調(diào)用
}
})
CommonJs
CommonJS是在瀏覽器環(huán)境之外構(gòu)建JavaScript生態(tài)系統(tǒng)為目標(biāo)產(chǎn)生的項(xiàng)目,比如服務(wù)器和桌面環(huán)境中船逮。CommonJS規(guī)范是為了解決JavaScript的作用域問題而定義的模塊形式顾腊,可以使每個(gè)模塊在它自身的命名空間中執(zhí)行。
該規(guī)范的主要內(nèi)容是:模塊必須通過 module.exports導(dǎo)出對外的變量或接口挖胃,通過require()來導(dǎo)入其他模塊的輸出到當(dāng)前模塊杂靶。
//定義模塊
exports.doStuff = function() {};
module.exports = someValue;
//引入模塊 -- 同步執(zhí)行梆惯,不用回調(diào)
require("module");
require("../file.js");
優(yōu)點(diǎn):
服務(wù)器端便于重用
NPM中已經(jīng)將近20w個(gè)模塊包
簡單并容易使用
缺點(diǎn):
同步的模塊方式不適合不適合在瀏覽器環(huán)境中,同步意味著阻塞加載伪煤,瀏覽器資源是異步加載的
不能非阻塞的并行加載多個(gè)模塊
實(shí)現(xiàn):node.js
nodejs中加袋,原生已經(jīng)實(shí)現(xiàn)了模塊化,已經(jīng)不需要導(dǎo)入第三方庫了抱既,可以直接require()
服務(wù)器端與瀏覽器端的技術(shù)選型职烧?
服務(wù)器端模塊化規(guī)范 -- CommonJS
老實(shí)說,在瀏覽器環(huán)境下防泵,沒有模塊也不是特別大的問題蚀之,畢竟網(wǎng)頁程序的復(fù)雜性有限;但是在服務(wù)器端捷泞,一定要有模塊足删,與操作系統(tǒng)和其他應(yīng)用程序互動(dòng),否則根本沒法編程锁右。
node.js的模塊系統(tǒng)失受,就是參照CommonJS規(guī)范實(shí)現(xiàn)的。在CommonJS中咏瑟,有一個(gè)全局性方法require()拂到,用于加載模塊
瀏覽器端 -- AMD(requirejs) CMD(Seajs)
因?yàn)榉?wù)器與APP都是加載的本地的資源,所以码泞,不用回調(diào)這種操作兄旬,同步依次上下執(zhí)行即可,導(dǎo)入操作 不會(huì)像瀏覽器端這樣余寥,占用太長時(shí)間领铐。
因?yàn)樯厦孢@個(gè)原因,瀏覽器端宋舷,只能選擇 AMD - CMD 兩種規(guī)范绪撵,異步執(zhí)行,不阻塞線程肥缔。
了解SeaJS莲兢,以及Seajs與requirejs之間的區(qū)別?
定義模塊 define
- 定義模塊
define(function(){})
- 函數(shù)體內(nèi)的方法屬性都屬于這個(gè)方法续膳,對外有封裝性;解決了命名沖突問題改艇,使js代碼有了封裝性
- 直接調(diào)用 jQuery 插件等非標(biāo)準(zhǔn)模塊的方法 http://my.oschina.net/briviowang/blog/208587
//定義模塊
/*
require
加載文件依賴、模塊依賴的坟岔,用于define函數(shù)體內(nèi)
在一個(gè)模塊系統(tǒng)中谒兄,`require` 加載過的模塊會(huì)被緩存
默認(rèn) `require` 是同步加載模塊的
exports 和 module.exports
module.exports曝露出一個(gè)完整的對象,只能扔一次只能曝露出來一個(gè)
exports是module.exports的別名社付,可以用來單個(gè)屬性承疲、方法邻耕、對象的曝露,用.的形式,exports能做的事情module.exports也可以做
*/
define(function(require, exports, module) {
var $ = require('jquery');
var Spinning = require('./spinning');
exports.doSomething = ...
module.exports = ...
})
啟動(dòng)模塊 seajs.use
- 加載入口模塊燕鸽,我們把define定義的js就叫模塊
- 這個(gè)用于在html代碼里面的加載
- seajs使用的時(shí)候兄世,可以先在配置文件中,修改base設(shè)置基本路徑啊研,以后加載御滩,都是相對seajs文件所在文件,但是安全起見党远,最好少用削解。
導(dǎo)入模塊
/*
第一參數(shù)是入口模塊的路徑
第二個(gè)函數(shù)是回調(diào)函數(shù)
*/
seajs.use('路徑',function(回調(diào)對象){
//此回調(diào)對象就是moudle.exports對象。我們可以使用定義模塊中沟娱,module.exports對象所有的屬性與方法
});
//seajs.use 和 Document 的 ready 沒有任何關(guān)系
//要想保證 文檔結(jié)構(gòu)加載完畢再執(zhí)行你的 js 代碼氛驮,一定要在 seajs.use 內(nèi)部通過 window.onload 或者 $(function(){})
requirejs與seajs的區(qū)別
requirejs是優(yōu)先加載的
seajs是懶加載的,就是有拖延癥济似,用的時(shí)候才加載