在後端,JavaScript的規範遠遠落後而且有不少缺陷,這使得難以使用JavaScript開發大型應用。好比:html
CommonJS規範 的提出,主要是爲了彌補JavaScript沒有標準的缺陷。CommonJS API將經過定義處理許多常見應用程序需求的API來填補這一空白,最終提供與Python,Ruby和Java同樣豐富的標準庫。以達到像Python、Ruby和Java那樣具有開發大型應用的基礎能力,而不是停留在開發瀏覽器端小腳本程序的階段。node
應用程序開發人員可以使用CommonJS API編寫應用程序,而後跨不一樣的JavaScript解釋器和主機環境運行該應用程序。json
CommonJS模塊規範主要分爲三部分:模塊引用、模塊定義、模塊標識。後端
//引入http模塊,並賦值給變量http var http = require('http');
require函數的基本功能是,讀入並執行一個JavaScript文件,而後返回該模塊的exports對象。當咱們用require()獲取module時,Node會根據module.id找到對應的module,並返回module. exports,這樣就實現了模塊的輸出。api
require函數使用一個參數,參數值能夠帶有完整路徑的模塊的文件名,也能夠爲模塊名。數組
require("./module/b"); //相對路徑 require("../node/module/c"); //絕對路徑
文件目錄結構以下:瀏覽器
CommonJS規範規定,一個文件就是一個模塊,用module變量表明當前模塊。 Node在其內部提供一個Module的構建函數。全部模塊都是Module的實例。實例代碼以下:服務器
function Module(id, parent) {
this.id = id; this.exports = {}; this.parent = parent; this.filename = null; this.loaded = false; this.children = []; } module.exports = Module; var module = new Module(filename, parent);
每一個模塊內部,都有一個module對象,表明當前模塊。它的屬性以下:網絡
exports 屬性是module對象的一個屬性,它向外提供接口。
如 2.1模塊引用 中示例,a.js引入b.js做爲一個模塊,當在b.js中定義以下方法時:異步
//加法 function add(num1,num2){ console.log(num1+num2); }
在a.js中調用卻報錯
var addMethod = require("./module/b"); //調用模塊中的add方法 addMethod.add(1,6);
b.js中的函數要能被其餘模塊使用,就須要暴露一個對外的接口,exports 屬性用於完成這一工做。b.js中的方法定義修改以下:
exports.add = function(num1,num2){ console.log(num1+num2); }
在a.js中可以調用。
模塊標識就是傳遞給require方法的參數,必須符合小駝峯命名的字符串,或者以.、..開頭的相對路徑,或者絕對路徑,默認文件名後綴.js。在Node實現中,正是基於這樣一個標識符進行模塊查找的,若是沒有發現指定模塊會報錯。
根據參數的不一樣格式,require命令去不一樣路徑尋找模塊文件。加載規則以下:
(1)若是參數字符串以「/」開頭,則表示加載的是一個位於絕對路徑的模塊文件。好比,require('/home/marco/foo.js')將加載/home/marco/foo.js。
(2)若是參數字符串以「./」開頭,則表示加載的是一個位於相對路徑(跟當前執行腳本的位置相比)的模塊文件。好比,require('./circle')將加載當前腳本同一目錄的circle.js。
(3)若是參數字符串不以「./「或」/「開頭,則表示加載的是一個默認提供的核心模塊(位於Node的系統安裝目錄中),或者一個位於各級node_modules目錄的已安裝模塊(全局安裝或局部安裝)。
舉例來講,腳本/home/user/projects/foo.js執行了require('bar.js')命令,Node會依次搜索如下文件。
/usr/local/lib/node/bar.js
/home/user/projects/node_modules/bar.js
/home/user/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
這樣設計的目的是,使得不一樣的模塊能夠將所依賴的模塊本地化。
(4)若是參數字符串不以「./「或」/「開頭,並且是一個路徑,好比require('example-module/path/to/file'),則將先找到example-module的位置,而後再以它爲參數,找到後續路徑。
(5)若是指定的模塊文件沒有發現,Node會嘗試爲文件名添加.js、.json、.node後,再去搜索。.js件會以文本格式的JavaScript腳本文件解析,.json文件會以JSON格式的文本文件解析,.node文件會以編譯後的二進制文件解析。
(6)若是想獲得require命令加載的確切文件名,使用require.resolve()方法。
CommonJS是同步的,意味着你想調用模塊裏的方法,必須先用require加載模塊。這對服務器端的Nodejs來講不是問題,由於模塊的JS文件都在本地硬盤上,CPU的讀取時間很是快,同步不是問題。但若是是瀏覽器環境,要從服務器加載模塊。模塊的加載將取決於網速,若是採用同步,網絡情緒不穩定時,頁面可能卡住,這就必須採用異步模式。因此,就有了 AMD解決方案。下一篇咱們開始介紹模塊化規範的AMD規範;
參考:
https://www.cnblogs.com/huiguo/p/7967241.html
https://nodejs.org/api/modules.html#modules_module_exports