模塊化初探

1. 為什么要使用模塊化?

隨著互聯(lián)網(wǎng)技術(shù)的發(fā)展,網(wǎng)頁的JavaScript代碼越來越龐大,越來越復(fù)雜,復(fù)雜的網(wǎng)頁通常需要團(tuán)隊(duì)分工合作、進(jìn)度管理等,開發(fā)者迫切需要能隔離、組織龐大的JavaScript代碼的功能,也就是這里所說的模塊化。
一個(gè)模塊就是一個(gè)實(shí)現(xiàn)特定功能的文件,有了模塊,我們就可以更方便地使用別人的代碼,想要什么功能,就加載什么模塊。同時(shí)還解決了命名沖突,變量污染等問題。
模塊化開發(fā)規(guī)范在前端先驅(qū)們的探索中一步步形成。從最開始的函數(shù)封裝 --->對(duì)象-->立即執(zhí)行函數(shù),到后來的CommonJS、AMD、CMD。

2. CommonJS、AMD、CMD

  • CommonJS規(guī)范

CommonJS是服務(wù)器端模塊的規(guī)范,Node.js采用了這個(gè)規(guī)范。Node.JS首先采用了js模塊化的概念。它的主要內(nèi)容:

  1. 定義模塊 根據(jù)CommonJS規(guī)范,一個(gè)單獨(dú)的文件就是一個(gè)模塊。每一個(gè)模塊都是一個(gè)單獨(dú)的作用域,也就是說,在該模塊內(nèi)部定義的變量,無法被其他模塊讀取,除非定義為global對(duì)象的屬性

  2. 模塊輸出: 模塊只有一個(gè)出口,module.exports對(duì)象,我們需要把模塊希望輸出的內(nèi)容放入該對(duì)象

  3. 加載模塊: 加載模塊使用require方法,該方法讀取一個(gè)文件并執(zhí)行,返回文件內(nèi)部的module.exports對(duì)象
    范例

     //模塊定義 myModel.js
      var name = 'Byron';
      function printName(){
        console.log(name);
      }
      module.exports = {
        printName: printName,
      }
    
      //加載模塊
      var nameModule = require('./myModel.js');
      nameModule.printName();
    

CommonJS的局限:由于require是同步的,模塊系統(tǒng)需要同步讀取模塊文件內(nèi)容,并編譯執(zhí)行以得到模塊接口。這在服務(wù)器端可以很好的執(zhí)行,因?yàn)槟K都放在本地硬盤,直接讀取就行了。但CommonJS卻不適合瀏覽器環(huán)境,比如:

       var math = require('math');
       math.add(2, 3);

后面的代碼執(zhí)行依賴于前面加載的模塊math,瀏覽器加載是異步的,如果加載時(shí)間很長(zhǎng),后面的代碼也無法執(zhí)行,會(huì)一直卡在那里。為了解決這個(gè)問題,誕生了AMD和CMD規(guī)范。

  • AMD

AMD 即Asynchronous Module Definition,中文名是異步模塊定義的意思。語法:

  1. define來定義模塊。
    define(id?, dependencies?, factory);
    • id:可選參數(shù),用來定義模塊的標(biāo)識(shí),如果沒有提供該參數(shù),腳本文件名(去掉拓展名)
    • dependencies:是一個(gè)當(dāng)前模塊依賴的模塊名稱數(shù)組
    • factory:工廠方法,模塊初始化要執(zhí)行的函數(shù)或?qū)ο蟆H绻麨楹瘮?shù),它應(yīng)該只被執(zhí)行一次。如果是對(duì)象,此對(duì)象應(yīng)該為模塊的輸出值
  2. require來加載模塊。
    require([dependencies], function(){});
    require()函數(shù)接受兩個(gè)參數(shù):
    • 第一個(gè)參數(shù)是一個(gè)數(shù)組,表示所依賴的模塊
    • 第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù),當(dāng)前面指定的模塊都加載成功后,它將被調(diào)用。加載的模塊會(huì)以參數(shù)形式傳入該函數(shù),從而在回調(diào)函數(shù)內(nèi)部就可以使用這些模塊
      require()函數(shù)在加載依賴的函數(shù)的時(shí)候是異步加載的,這樣瀏覽器不會(huì)失去響應(yīng),它指定的回調(diào)函數(shù),只有前面的模塊都加載成功后,才會(huì)運(yùn)行,解決了依賴性的問題。
  • CMD

CMD([Common Module Definition] 模塊定義規(guī)范。在 CMD 規(guī)范中,一個(gè)模塊就是一個(gè)文件。代碼的書寫格式如下:
define(function(require, exports, module) {
// 模塊代碼
});
require 是一個(gè)方法,接受 模塊標(biāo)識(shí) 作為唯一參數(shù),用來獲取其他模塊提供的接口;exports 是一個(gè)對(duì)象,用來向外提供模塊接口;module 是一個(gè)對(duì)象,上面存儲(chǔ)了與當(dāng)前模塊相關(guān)聯(lián)的一些屬性和方法。

AMD和CMD的區(qū)別

  1. AMD 是 RequireJS 在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出。
    CMD 是 SeaJS 在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出。

  2. AMD:提前執(zhí)行(異步加載:依賴先執(zhí)行)+延遲執(zhí)行。
    CMD:延遲執(zhí)行(運(yùn)行到需加載,根據(jù)順序執(zhí)行)。
    CMD 推崇依賴就近,AMD 推崇依賴前置。

     // CMD
     define(function(require, exports, module) {
     var a = require('./a')
     a.doSomething()
     // 此處略去 100 行
     var b = require('./b') // 依賴可以就近書寫
     b.doSomething()
     // ... 
     })
    
     // AMD 默認(rèn)推薦的是
     define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好
     a.doSomething()
     // 此處略去 100 行
     b.doSomething()
     ...
     }) 
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容