模塊化的開發(fā)方式可以提高代碼復(fù)用率,方便進(jìn)行代碼的管理袒餐。通常一個(gè)文件就是一個(gè)模塊飞蛹,有自己的作用域,只向外暴露它的接口灸眼。目前流行的js模塊化規(guī)范有CommonJS卧檐、AMD、CMD以及ES6的模塊系統(tǒng)焰宣。
-
<script>
標(biāo)簽- 全局作用域下容易造成變量沖突
- 文件只能按照
<script>
的書寫順序進(jìn)行加載 - 開發(fā)人員必須主觀解決模塊和代碼庫的依賴關(guān)系
- 在大型項(xiàng)目中各種資源難以管理霉囚,長期積累的問題導(dǎo)致代碼庫混亂不堪
-
CommonJS
- 定義的模塊分為: 模塊引用(require) / 模塊輸出(exports) / 模塊標(biāo)識(shí)(module)
- 是更偏向于服務(wù)器端的規(guī)范。NodeJS采用了這個(gè)規(guī)范匕积。CommonJS的一個(gè)模塊就是一個(gè)腳本文件盈罐。require命令第一次加載該腳本時(shí)就會(huì)執(zhí)行整個(gè)腳本榜跌,然后在內(nèi)存中生成一個(gè)對(duì)象。
- CommonJS是同步加載模塊盅粪,這對(duì)于服務(wù)器端不是一個(gè)問題钓葫,因?yàn)樗械哪K都放在本地硬盤。等待模塊時(shí)間就是硬盤讀取文件時(shí)間票顾,很小础浮。但是,對(duì)于瀏覽器而言奠骄,它需要從服務(wù)器加載模塊豆同,涉及到網(wǎng)速,代理等原因戚揭,一旦等待時(shí)間過長诱告,瀏覽器處于”假死”狀態(tài)。所以在瀏覽器端民晒,不適合于CommonJS規(guī)范精居。
{ id:'...', exports: { ... }, loaded: true, ... } /* id是模塊名,exports是該模塊導(dǎo)出的接口潜必,loaded表示模塊是否加載完畢靴姿。 此外還有很多屬性,這里省略了磁滚。 以后需要用到這個(gè)模塊時(shí)佛吓,就會(huì)到exports屬性上取值。 即使再次執(zhí)行require命令垂攘,也不會(huì)再次執(zhí)行該模塊维雇,而是到緩存中取值。*/ // 例: math.jsexports.add = function(a, b) { return a + b; } var math = require('math'); math.add(2, 3);
-
AMD (Asynchronous Module Definition) 異步模塊定義
- AMD是RequireJs在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出
- 這里異步指的是不堵塞瀏覽器其他任務(wù)(dom構(gòu)建晒他,css渲染等)吱型,而加載內(nèi)部是同步的(加載完模塊后立即執(zhí)行回調(diào))。
-
依賴前置
/* AMD也采用require命令加載模塊陨仅,但是不同于CommonJS津滞,它要求兩個(gè)參數(shù):*/ require([module], callback); /* 第一個(gè)參數(shù)[module],是一個(gè)數(shù)組灼伤,里面的成員是要加載的模塊触徐,callback是加載完成后的回調(diào)函數(shù)。 如果將上述的代碼改成AMD方式:*/ require(['math'], function(math) { math.add(2, 3); }) //其中狐赡,回調(diào)函數(shù)中參數(shù)對(duì)應(yīng)數(shù)組中的成員(模塊)撞鹉。 //修改為define的寫法: // math.js define(['dependenceModule'], function(dependenceModule) var add = function(x, y) { return x + y; } return { add: add } }) /* 當(dāng)require()函數(shù)加載math模塊的時(shí)候,就會(huì)先加載dependenceModule模塊。 當(dāng)有多個(gè)依賴時(shí)孔祸,就將所有的依賴都寫在define()函數(shù)第一個(gè)參數(shù)數(shù)組中隆敢。 所以說AMD是依賴前置的发皿。這不同于CMD規(guī)范崔慧,它是依賴就近的。*/
-
CMD (Common Module Definition)
- Seajs推崇的規(guī)范
-
依賴就近穴墅,用的時(shí)候再require, 推崇 as lazy as possible(盡可能的懶加載惶室,也稱為延遲加載,即在需要的時(shí)候才加載)玄货。
// CMD define(function(require, exports, module) { var a = require('./a'); a.doSomething(); var b = require('./b'); b.doSomething(); }) //AMD define(['a', 'b'], function(a, b) { a.doSomething(); b.doSomething(); })
- CMD和AMD的區(qū)別
- AMD和CMD都是用difine和require的異步加載
- 但是CMD標(biāo)準(zhǔn)傾向于在使用過程中提出依賴皇钞,就是不管代碼寫到哪突然發(fā)現(xiàn)需要依賴另一個(gè)模塊,那就在當(dāng)前代碼用require引入就可以了松捉,規(guī)范會(huì)幫你搞定預(yù)加載
- AMD標(biāo)準(zhǔn)讓你必須提前在頭部依賴參數(shù)部分寫好(沒有寫好夹界? 倒回去寫好咯)。
-
ES6 模塊
- ES6 模塊不是對(duì)象隘世,無法引用模塊本身可柿。而是通過export命令顯式指定輸出的代碼,再通過import命令輸入丙者。
- ES6 可以在編譯時(shí)就完成模塊加載复斥,效率要比 CommonJS 模塊的加載方式高
- 頂層的this指向undefined
- 瀏覽器加載 ES6 模塊,也使用<script>標(biāo)簽械媒,但是要加入type="module"屬性目锭。瀏覽器對(duì)于帶有type="module"的<script>,都是異步加載纷捞,不會(huì)造成堵塞瀏覽器痢虹。
<script type="module" src="./foo.js"></script>
-
import和require的區(qū)別
- vue模塊引入使用import,node模塊引入使用require
- require 是 AMD規(guī)范引入方式主儡,import是es6的一個(gè)語法標(biāo)準(zhǔn)奖唯,如果要兼容瀏覽器的話必須轉(zhuǎn)化成es5的語法
- 通過require引入基礎(chǔ)數(shù)據(jù)類型時(shí),屬于復(fù)制該變量缀辩。通過require引入復(fù)雜數(shù)據(jù)類型時(shí)臭埋,數(shù)據(jù)淺拷貝該對(duì)象