隨着前端js代碼複雜度的提升,js模塊化是必然趨勢,不只好維護,同時依賴很明確,不會全局污染,今天整理一下模塊化的幾個規範吧~html
script標籤引入js文件,相互羅列,可是被依賴的放在前面,不然使用就會報錯。以下:前端
<script src="jquery.js"></script>
<script src="jquery_scroller.js"></script>
<script src="main.js"></script>
<script src="other1.js"></script>
<script src="other2.js"></script>
<script src="other3.js"></script>複製代碼
即簡單的將全部的js文件通通放在一塊兒。可是這些文件的順序還不能出錯,好比jquery須要先引入,才能引入jquery插件,才能在其餘的文件中使用jquery。缺點很明顯:
node
該規範最初是用在服務器端的node的,它有四個重要的環境變量爲模塊化的實現提供支持:module
、exports
、require
、global
。實際使用時,用module.exports
定義當前模塊對外輸出的接口(不推薦直接用exports
),用require
加載模塊(同步)。jquery
// a-commonJs.js (導出)
var a = 5;var add = function(param){//在這裏寫上須要向外暴露的函數、變量 return a + param}module.exports.a = a;module.exports.add = add===========================
// b-commonJs.js引用自定義模塊,參數包含路徑,可省略.js(導入)
var addFn = require('./a-commonJs')console.log(addFn.add(3)) //8console.log(addFn.a) //5複製代碼
一點說明: es6
exports 是對 module.exports 的引用。好比咱們能夠認爲在一個模塊的頂部有這句代碼: exports = module.exports因此,咱們不能直接給exports賦值,好比number、function等。 複製代碼
注意:由於module.exports自己就是一個對象,因此,咱們在導出時可使用 瀏覽器
module.exports = {foo: 'bar'} //true
緩存
module.exports.foo = 'bar' //true
。bash
可是, exports 是 module.exports 的一個引用,或者理解爲exports是一個指針,exports指向module.exports,這樣,咱們就只能使用 exports.foo = 'bar'
的方式,而不能使用服務器
exports = {foo: 'bar'} //error 這種方式是錯誤的,至關於從新定義了exports
babel
一點優勢:解決了依賴、全局變量污染的問題
一點缺點: CommonJS用同步的方式加載模塊。在服務端,模塊文件都存在本地磁盤,讀取很是快,因此這樣作不會有問題。可是在瀏覽器端,限於網絡緣由,CommonJS不適合瀏覽器端模塊加載,更合理的方案是使用異步加載,好比下邊AMD規範。
承接上文,AMD規範則是非同步加載模塊,容許指定回調函數,AMD 是 RequireJS 在推廣過程當中對模塊定義的規範化產出。。
AMD標準中,定義了下面三個API:
require([module], callback)
define(id, [depends], callback)
require.config()
即經過define來定義一個模塊,而後使用require來加載一個模塊, 使用require.config()指定引用路徑。
先到require.js官網下載最新版本,而後引入到頁面,以下:
<script data-main="./alert" src="./require.js"></script>
data-main屬性不能省略。
以上分別是定義模塊,引用模塊,運行在瀏覽器彈出提示信息。
引用模塊的時候,咱們將模塊名放在[]
中做爲reqiure()
的第一參數;若是咱們定義的模塊自己也依賴其餘模塊,那就須要將它們放在[]
中做爲define()
的第一參數。
在使用require.js的時候,咱們必需要提早加載全部的依賴,而後纔可使用,而不是須要使用時再加載。
一點優勢:適合在瀏覽器環境中異步加載模塊、並行加載多個模塊
一點缺點:不能按需加載、開發成本大
AMD 推崇依賴前置、提早執行,CMD推崇依賴就近、延遲執行。CMD 是 SeaJS 在推廣過程當中對模塊定義的規範化產出。
很明顯,CMD是按需加載,就近原則。
在ES6中,咱們可使用 import 關鍵字引入模塊,經過 exprot 關鍵字導出模塊,功能較之於前幾個方案更爲強大,也是咱們所推崇的,可是因爲ES6目前沒法在瀏覽器中執行,因此,咱們只能經過babel將不被支持的import編譯爲當前受到普遍支持的 require。
es6在導出的時候有一個默認導出,export default
,使用它導出後,在import的時候,不須要加上{},模塊名字能夠隨意起。該名字實際上就是個對象,包含導出模塊裏面的函數或者變量。
可是一個模塊只能有一個export default
。
如下引用阮一峯老師的內容:
import
,就會生成一個只讀引用。等到腳本真正執行時,再根據這個只讀引用,到被加載的那個模塊裏面去取值。換句話說,ES6 的import
有點像 Unix 系統的「符號鏈接」,原始值變了,import
加載的值也會跟着變。所以,ES6 模塊是動態引用,而且不會緩存值,模塊裏面的變量綁定其所在的模塊。運行時加載: CommonJS 模塊就是對象;即在輸入時是先加載整個模塊,生成一個對象,而後再從這個對象上面讀取方法,這種加載稱爲「運行時加載」。
編譯時加載: ES6 模塊不是對象,而是經過 export
命令顯式指定輸出的代碼,import
時採用靜態命令的形式。即在import
時能夠指定加載某個輸出值,而不是加載整個模塊,這種加載稱爲「編譯時加載」。
CommonJS 加載的是一個對象(即module.exports
屬性),該對象只有在腳本運行完纔會生成。而 ES6 模塊不是對象,它的對外接口只是一種靜態定義,在代碼靜態解析階段就會生成。
一點說明:本文只是本身的一點筆記,方便本身記憶和理解。\(^o^)/~