題目1: 為什么要使用模塊化?
模塊化可以使代碼低耦合栅受,功能模塊直接不相互影響将硝。
1.可維護(hù)性:根據(jù)定義,每個(gè)模塊都是獨(dú)立的屏镊。良好設(shè)計(jì)的模塊會(huì)盡量與外部的代碼撇清關(guān)系依疼,以便于獨(dú)立對(duì)其進(jìn)行改進(jìn)和維護(hù)。維護(hù)一個(gè)獨(dú)立的模塊比起一團(tuán)凌亂的代碼來(lái)說(shuō)要輕松很多而芥。
2.命名空間:在JavaScript中律罢,最高級(jí)別的函數(shù)外定義的變量都是全局變量(這意味著所有人都可以訪問(wèn)到它們)。也正因如此棍丐,當(dāng)一些無(wú)關(guān)的代碼碰巧使用到同名變量的時(shí)候误辑,我們就會(huì)遇到“命名空間污染”的問(wèn)題。
3.提高代碼的可復(fù)用性歌逢。
4.進(jìn)行依賴管理巾钉。
題目2: CMD、AMD秘案、CommonJS 規(guī)范分別指什么砰苍?有哪些應(yīng)用
Asynchronous Module Definition (AMD)/(異步模塊定義)
它推崇依賴前置,采用異步方式加載模塊阱高,模塊的加載不影響它后面語(yǔ)句的運(yùn)行赚导。所有依賴這個(gè)模塊的語(yǔ)句,都定義在一個(gè)回調(diào)函數(shù)中赤惊,等到加載完成之后吼旧,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行。
特點(diǎn)/缺點(diǎn):
- 依賴前置,需要在定義的時(shí)候未舟,寫(xiě)好需要的依賴圈暗。
- 多個(gè)JS有依賴關(guān)系。被依賴的JS需要早于依賴它的文件提前加入处面。
- JS加載的時(shí)候厂置,頁(yè)面會(huì)停止渲染。加載的文件越多魂角。頁(yè)面失去響應(yīng)的時(shí)間越長(zhǎng)。
應(yīng)用:Reauire.js
//定義模塊:
define(id ?, dependencies?, function)
-----------------------------------------------
//id:可選參數(shù),用來(lái)定義模塊標(biāo)識(shí)智绸。如果沒(méi)有寫(xiě)野揪,就用文件名访忿。
//denpendencies:當(dāng)前的模塊依賴的模塊,數(shù)組形式斯稳。
//function:執(zhí)行的函數(shù)
//加載模塊
require([dependencies], function)
//---------------------------------------------
//dependencies:當(dāng)前模塊需要的依賴的模塊海铆。
//function:回調(diào)函數(shù),在模塊加載完了后挣惰,會(huì)被執(zhí)行卧斟。
//require是異步執(zhí)行。在依賴模塊沒(méi)有被加載完憎茂。是不會(huì)執(zhí)行回調(diào)函數(shù)的珍语。同時(shí)瀏覽器不會(huì)失去響應(yīng)。
Common Module Definition ——(CMD)
通用模塊定義,是一種模塊定義方式和模塊加載方式的規(guī)范
- 依賴就近竖幔,需要的時(shí)候再引入這個(gè)依賴項(xiàng)板乙,用的時(shí)候再require。
- 推崇一個(gè)文件一個(gè)模塊拳氢,所以經(jīng)常將文件名作為模塊id
- 因推崇依賴就近募逞,所以一般不在define的參數(shù)中寫(xiě)依賴,在factory中寫(xiě)馋评。
應(yīng)用:sea.js
define(function(require,exports,module){})
//require:獲取其他的模塊提供的接口放接。
//exports:對(duì)外提供模塊的接口。
//module是個(gè)對(duì)象留特,上面存儲(chǔ)了與當(dāng)前模塊相關(guān)的屬性和方法
//定義模塊
define(function(require, exports, module){
var $ = require('jquery.js')
$('div').removeClass('active')
})
//加載模塊
seajs.use(['myModule.js'], function(my){
})
AMD與CMD的差別是:AMD是首先加載所有模塊纠脾,再執(zhí)行,而CMD是按需加載磕秤。AMD依賴前置乳乌,js可以方便知道依賴模塊是誰(shuí),立即加載市咆;而CMD就近依賴汉操,需要使用把模塊變?yōu)樽址馕鲆槐椴胖酪蕾嚵四切┠K,這也是很多人詬病CMD的一點(diǎn)蒙兰,犧牲性能來(lái)帶來(lái)開(kāi)發(fā)的便利性磷瘤,實(shí)際上解析模塊用的時(shí)間短到可以忽略。如今requireJS和seaJS都已經(jīng)是過(guò)去時(shí)搜变,webpack和Browserify成為主流
CommonJS
- 一個(gè)單獨(dú)的文件就是一個(gè)模塊采缚,每個(gè)模塊都是一個(gè)單獨(dú)的作用域
在模塊內(nèi)部定義的變量,無(wú)法被其他模塊讀取挠他,除非定義為global對(duì)象的屬性 - 模塊輸出:模塊只有一個(gè)出口扳抽,module.exports對(duì)象,我們需要把模塊希望輸出的內(nèi)容放入該對(duì)象
- 加載模塊:加載模塊使用require方法,該方法讀取一個(gè)文件并執(zhí)行贸呢,返回 文件內(nèi)部的module.exports對(duì)象镰烧,如果請(qǐng)求的模塊不能返回,那么”require”必須拋出一個(gè)錯(cuò)誤楞陷。
//定義模塊 myModule.js
var name = 'mamba'
function printName(){
console.log(name)
}
function printFullName(firstName){
console.log(firstName + name);
}
//輸出模塊
module.exports = {
printName: printName,
printFullName: printFullName
}
//加載模塊
var nameModule = require('./myModule.js') //不同的實(shí)現(xiàn)對(duì)require時(shí)的路徑有不同要求怔鳖,一般情況可以省略js拓展名,可以使用相對(duì)路徑固蛾,也可以使用絕對(duì)路徑结执,甚至可以省略路徑直接使用模塊名(前提是該模塊是系統(tǒng)內(nèi)置模塊)
//使用模塊
nameModule.printName();
應(yīng)用:因?yàn)閞equire是同步的,所以主要在服務(wù)器端使用
瀏覽器端加載JavaScript是異步的艾凯,所以傳統(tǒng)的CommonJS在瀏覽器環(huán)境中無(wú)法正常加載献幔。