模塊化就是將系統分解成一個一個獨立的功能模塊,模塊是獨立的,可複用的,模塊之間是解耦的。
CommonJS
Commonjs模塊是一個可複用的js塊,通過exports輸出這個特定對象,其他模塊通過require()引用此對象;
CommonJS支持無封裝的模塊(即沒有定義的相關語句),把我們從AMD的define()封裝中解放出來;
CommonJS只支持對象作爲模塊;
1 //package/lib is a dependency we require 2 var lib = require("package/lib"); 3 4 //behaviour for our module 5 function foo(){ 6 lib.log("hello world!") 7 } 8 9 //export (expose) foo to other modules 10 exports.foo = foo
Node應用由模塊組成,採用commonjs模塊規範,每個文件是一個模塊,有自己的作用域。
commonjs規範規定,每個模塊內部,module變量代表當前模塊。這個變量是一個對象,它的
exports屬性(module.exports)是對外的接口。require方法用於加載模塊
1 //example.js 2 var x=5; 3 var foo = function(v){ 4 return v + x; 5 }; 6 module.exports.x = x; 7 module.exports.foo = foo; 8 9 //test.js 10 var example = require('./example.js'); 11 console.log(example.x);//5 12 console.log(example.foo(1))//6
不同的實現對require時的路徑有不同要求,一般情況可以省略js
拓展名,可以使用相對路徑,也可以使用絕對路徑,甚至可以省略路徑直接使用模塊名(前提是該模塊是系統內置模塊)
commonJs模塊特點:
1.所有代碼都運行在模塊作用域,不會污染全局作用域
2.模塊可多次加載,但只在第一次加載運行,運行結果會存儲在緩存,後面加載直接讀取緩存,必須清除緩存才能讓模塊再次運行;
3.模塊採用同步運行方式,按照在代碼中出現但順序進行加載
module.exports屬性
module.exports屬性表示當前模塊對外輸出但接口,其他文件加載該模塊就是讀取module.exports變量;
exports變量
爲了方便,Node爲每個模塊提供一個exports變量,指向module.exports;這等同於在每個模塊的頭部都有一行一下命令:
1 var exports = module.exports
即,在對外輸出模塊接口時,可以向exports對象添加方法
1 exports.area = function (r) { 2 return Math.PI * r * r; 3 };
注意,不能直接將exports變量指向一個值,因爲這樣等於切斷了exports
與module.exports
的聯繫。
即 exports = function(r){return Math.PI*r*r;}是無效的。
1 exports.hello = function(){ 2 return 'hele'; 3 } 4 module.exports = 'Hello world';
上面代碼中,hello函數是無法輸出的,因爲下面module.exports被重新賦值了。
AMD(Asynchronous Module Defination,瀏覽器端js模塊化)
異步模塊定義規範,使用異步方式加載模塊,通過define方法定義模塊,require方法加載模塊。
由於不是JavaScript原生支持,使用AMD規範進行頁面開發需要用到對應的庫函數RequireJS
,實際上AMD 是 RequireJS 在推廣過程中對模塊定義的規範化的產出;
異步加載模塊,模塊的加載不影響它後面語句的運行,所有依賴這個模塊的語句,都定義在回調函數中,等加載完成
後,這個回調函數纔會運行。
1 //定義模塊myModule.js 2 define(['dependency'],function(){ 3 var name = 'Bily'; 4 function printName(){ 5 console.log(name); 6 } 7 return { 8 printName: printName 9 } 10 }) 11 //加載模塊 12 require(['myModule],function(my){ 13 my.printName(); 14 })
requireJS定義了一個函數define,它是全局變量,用來定義模塊
define(id?, dependencies? factory)
id:可選參數,用來定義模塊的標識,如果沒有提供該參數,就用腳本文件名(去掉擴展名)
dependencies: 當前模塊依賴的模塊名稱數組
factory: 工廠方法,模塊初始化要執行的函數或對象。如果是函數,它應該只被執行一次。如果是對象,此對象應該
爲模塊的輸出值
在文件中使用require函數加載模塊
require([dependencies],function(res){})
[dependencies] :第一個參數是數組,表示所依賴的模塊
function : 第二個參數是一個回調函數,當前面指定的模塊都加載成功後,它會被調用;加載的模塊會以參數形式傳入該函數,從而在回調函數內部可以使用這些模塊;
require()函數在加載依賴的函數的時候是異步加載的,這樣瀏覽器不會失去響應,它指定的回調函數,只有在前面的
模塊都加載成功後,纔會運行,解決了依賴性的問題;
模塊化就是將系統分解成一個一個獨立的功能模塊,模塊是獨立的,可複用的,模塊之間是解耦的。
CommonJS
Commonjs模塊是一個可複用的js塊,通過exports輸出這個特定對象,其他模塊通過require()引用此對象;
CommonJS支持無封裝的模塊(即沒有定義的相關語句),把我們從AMD的define()封裝中解放出來;
CommonJS只支持對象作爲模塊;
1 //package/lib is a dependency we require 2 var lib = require("package/lib"); 3 4 //behaviour for our module 5 function foo(){ 6 lib.log("hello world!") 7 } 8 9 //export (expose) foo to other modules 10 exports.foo = foo
Node應用由模塊組成,採用commonjs模塊規範,每個文件是一個模塊,有自己的作用域。
commonjs規範規定,每個模塊內部,module變量代表當前模塊。這個變量是一個對象,它的
exports屬性(module.exports)是對外的接口。require方法用於加載模塊
1 //example.js 2 var x=5; 3 var foo = function(v){ 4 return v + x; 5 }; 6 module.exports.x = x; 7 module.exports.foo = foo; 8 9 //test.js 10 var example = require('./example.js'); 11 console.log(example.x);//5 12 console.log(example.foo(1))//6
不同的實現對require時的路徑有不同要求,一般情況可以省略js
拓展名,可以使用相對路徑,也可以使用絕對路徑,甚至可以省略路徑直接使用模塊名(前提是該模塊是系統內置模塊)
commonJs模塊特點:
1.所有代碼都運行在模塊作用域,不會污染全局作用域
2.模塊可多次加載,但只在第一次加載運行,運行結果會存儲在緩存,後面加載直接讀取緩存,必須清除緩存才能讓模塊再次運行;
3.模塊採用同步運行方式,按照在代碼中出現但順序進行加載
module.exports屬性
module.exports屬性表示當前模塊對外輸出但接口,其他文件加載該模塊就是讀取module.exports變量;
exports變量
爲了方便,Node爲每個模塊提供一個exports變量,指向module.exports;這等同於在每個模塊的頭部都有一行一下命令:
1 var exports = module.exports
即,在對外輸出模塊接口時,可以向exports對象添加方法
1 exports.area = function (r) { 2 return Math.PI * r * r; 3 };
注意,不能直接將exports變量指向一個值,因爲這樣等於切斷了exports
與module.exports
的聯繫。
即 exports = function(r){return Math.PI*r*r;}是無效的。
1 exports.hello = function(){ 2 return 'hele'; 3 } 4 module.exports = 'Hello world';
上面代碼中,hello函數是無法輸出的,因爲下面module.exports被重新賦值了。
AMD(Asynchronous Module Defination,瀏覽器端js模塊化)
異步模塊定義規範,使用異步方式加載模塊,通過define方法定義模塊,require方法加載模塊。
由於不是JavaScript原生支持,使用AMD規範進行頁面開發需要用到對應的庫函數RequireJS
,實際上AMD 是 RequireJS 在推廣過程中對模塊定義的規範化的產出;
異步加載模塊,模塊的加載不影響它後面語句的運行,所有依賴這個模塊的語句,都定義在回調函數中,等加載完成
後,這個回調函數纔會運行。
1 //定義模塊myModule.js 2 define(['dependency'],function(){ 3 var name = 'Bily'; 4 function printName(){ 5 console.log(name); 6 } 7 return { 8 printName: printName 9 } 10 }) 11 //加載模塊 12 require(['myModule],function(my){ 13 my.printName(); 14 })
requireJS定義了一個函數define,它是全局變量,用來定義模塊
define(id?, dependencies? factory)
id:可選參數,用來定義模塊的標識,如果沒有提供該參數,就用腳本文件名(去掉擴展名)
dependencies: 當前模塊依賴的模塊名稱數組
factory: 工廠方法,模塊初始化要執行的函數或對象。如果是函數,它應該只被執行一次。如果是對象,此對象應該
爲模塊的輸出值
在文件中使用require函數加載模塊
require([dependencies],function(res){})
[dependencies] :第一個參數是數組,表示所依賴的模塊
function : 第二個參數是一個回調函數,當前面指定的模塊都加載成功後,它會被調用;加載的模塊會以參數形式傳入該函數,從而在回調函數內部可以使用這些模塊;
require()函數在加載依賴的函數的時候是異步加載的,這樣瀏覽器不會失去響應,它指定的回調函數,只有在前面的
模塊都加載成功後,纔會運行,解決了依賴性的問題;
CMD(Common Module Definition,通用模塊定義)
cmd在模塊定義和模塊加載時機上和amd不同,並且CMD需要額外引入第三方的庫文件,SeaJS;
seaJS推崇一個模塊一個文件
define是一個全局函數,用來定義模塊
define (id? , dependences?, factory)
參數id:可選,字符串類型,模塊標識,如果沒有提供參數,默認是文件名;
參數dependences:可選,字符串數組,當前模塊依賴的模塊,CMD推崇依賴就近;
參數factory:回調函數,工廠方法,初始化模塊需要執行的函數或對象,如果爲函數,它只被執行
一次,如果爲對象,此對象會作爲模塊的輸出值;
1 // cmd1.js 2 define(function(require,exports,module){ 3 // ... 4 module.exports={ 5 // ... 6 } 7 }) 8 9 // cmd2.js 10 define(function(require,exports,module){ 11 var cmd2 = require('./cmd1') 12 // cmd2.xxx 依賴就近書寫 13 module.exports={ 14 // ... 15 } 16 })
對外提供接口:給exports對象添加成員,或者使用retutn直接向外提供接口
ADM和CMD區別,AMD提前執行依賴的模塊即依賴前置,而後者是在用的之前,即依賴就近,只有在需要用到
某個模塊的時候才requrie;
ES6模塊化
ES6在語言標準的層面上,實現了模塊功能,可取代commonjs和AMD規範,成爲瀏覽器和服務器通用的模塊解決方案;
ES6設計思想是儘量靜態化,使得在編譯時就能確定模塊的依賴關係,以及輸入和輸出變量;而CommonJS和AMD
只能在運行時才能確定;
Es6模塊不是對象,而是通過export命令顯示指定輸出的代碼,再通過import命令輸入;
// ES6模塊
import { stat, exists, readFile } from 'fs';
上面代碼實質是從fs模塊加載3個方法,其他方法不加載,這種加載稱爲“編譯時加載”或靜態加載,即ES6可以在編譯時就完成
模塊加載,效率要比CommonJS模塊的加載方式高,這也導致沒法引用ES6模塊本身,因爲它不是對象。
ES6的模塊自動採用嚴格模式,不管你有沒有在模塊頭部加‘use strict’;
尤其注意,在模塊中,頂層this指向undefined,即不可在頂層代碼使用this;