題目1: 為什么要使用模塊化?
模塊化可以使代碼低耦合,功能模塊直接不相互影響。
1.可維護性:根據(jù)定義,每個模塊都是獨立的。良好設計的模塊會盡量與外部的代碼撇清關系,以便于獨立對其進行改進和維護。維護一個獨立的模塊比起一團凌亂的代碼來說要輕松很多。
2.命名空間:在JavaScript中,最高級別的函數(shù)外定義的變量都是全局變量(這意味著所有人都可以訪問到它們)。也正因如此,當一些無關的代碼碰巧使用到同名變量的時候,我們就會遇到“命名空間污染”的問題。
3.提高代碼的可復用性。
4.進行依賴管理。
題目2: CMD、AMD、CommonJS 規(guī)范分別指什么?有哪些應用
Asynchronous Module Definition (AMD)/(異步模塊定義)
它推崇依賴前置,采用異步方式加載模塊,模塊的加載不影響它后面語句的運行。所有依賴這個模塊的語句,都定義在一個回調(diào)函數(shù)中,等到加載完成之后,這個回調(diào)函數(shù)才會運行。
特點/缺點:
- 依賴前置,需要在定義的時候,寫好需要的依賴。
- 多個JS有依賴關系。被依賴的JS需要早于依賴它的文件提前加入。
- JS加載的時候,頁面會停止渲染。加載的文件越多。頁面失去響應的時間越長。
應用:Reauire.js
//定義模塊:
define(id ?, dependencies?, function)
-----------------------------------------------
//id:可選參數(shù),用來定義模塊標識。如果沒有寫,就用文件名。
//denpendencies:當前的模塊依賴的模塊,數(shù)組形式。
//function:執(zhí)行的函數(shù)
//加載模塊
require([dependencies], function)
//---------------------------------------------
//dependencies:當前模塊需要的依賴的模塊。
//function:回調(diào)函數(shù),在模塊加載完了后,會被執(zhí)行。
//require是異步執(zhí)行。在依賴模塊沒有被加載完。是不會執(zhí)行回調(diào)函數(shù)的。同時瀏覽器不會失去響應。
Common Module Definition ——(CMD)
通用模塊定義,是一種模塊定義方式和模塊加載方式的規(guī)范
- 依賴就近,需要的時候再引入這個依賴項,用的時候再require。
- 推崇一個文件一個模塊,所以經(jīng)常將文件名作為模塊id
- 因推崇依賴就近,所以一般不在define的參數(shù)中寫依賴,在factory中寫。
應用:sea.js
define(function(require,exports,module){})
//require:獲取其他的模塊提供的接口。
//exports:對外提供模塊的接口。
//module是個對象,上面存儲了與當前模塊相關的屬性和方法
//定義模塊
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可以方便知道依賴模塊是誰,立即加載;而CMD就近依賴,需要使用把模塊變?yōu)樽址馕鲆槐椴胖酪蕾嚵四切┠K,這也是很多人詬病CMD的一點,犧牲性能來帶來開發(fā)的便利性,實際上解析模塊用的時間短到可以忽略。如今requireJS和seaJS都已經(jīng)是過去時,webpack和Browserify成為主流
CommonJS
- 一個單獨的文件就是一個模塊,每個模塊都是一個單獨的作用域
在模塊內(nèi)部定義的變量,無法被其他模塊讀取,除非定義為global對象的屬性 - 模塊輸出:模塊只有一個出口,module.exports對象,我們需要把模塊希望輸出的內(nèi)容放入該對象
- 加載模塊:加載模塊使用require方法,該方法讀取一個文件并執(zhí)行,返回 文件內(nèi)部的module.exports對象,如果請求的模塊不能返回,那么”require”必須拋出一個錯誤。
//定義模塊 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') //不同的實現(xiàn)對require時的路徑有不同要求,一般情況可以省略js拓展名,可以使用相對路徑,也可以使用絕對路徑,甚至可以省略路徑直接使用模塊名(前提是該模塊是系統(tǒng)內(nèi)置模塊)
//使用模塊
nameModule.printName();
應用:因為require是同步的,所以主要在服務器端使用
瀏覽器端加載JavaScript是異步的,所以傳統(tǒng)的CommonJS在瀏覽器環(huán)境中無法正常加載。