Node.js相關——CommonJS規範

1. CommonJS規範產生背景

在後端,JavaScript的規範遠遠落後而且有不少缺陷,這使得難以使用JavaScript開發大型應用。好比:html

  • 沒有模塊系統
  • 標準庫較少
  • 沒有標準接口
  • 缺少包管理系統

CommonJS規範 的提出,主要是爲了彌補JavaScript沒有標準的缺陷。CommonJS API將經過定義處理許多常見應用程序需求的API來填補這一空白,最終提供與Python,Ruby和Java同樣豐富的標準庫。以達到像Python、Ruby和Java那樣具有開發大型應用的基礎能力,而不是停留在開發瀏覽器端小腳本程序的階段。node

應用程序開發人員可以使用CommonJS API編寫應用程序,而後跨不一樣的JavaScript解釋器和主機環境運行該應用程序。json

2. CommonJS模塊規範

CommonJS模塊規範主要分爲三部分:模塊引用、模塊定義、模塊標識。後端

2.1 模塊引用

//引入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");  //絕對路徑

文件目錄結構以下:瀏覽器

2.2 模塊定義

2.2.1 模塊(module)是什麼

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對象,表明當前模塊。它的屬性以下:網絡

  • module.id 模塊的識別符,一般是帶有絕對路徑的模塊文件名。
  • module.filename 模塊的文件名,帶有絕對路徑。
  • module.loaded 返回一個布爾值,表示模塊是否已經完成加載。
  • module.parent 返回一個對象,表示調用該模塊的模塊。
  • module.children 返回一個數組,表示該模塊要用到的其餘模塊。
  • module.exports 初始值爲一個空對象{},表示模塊對外輸出的接口。

2.2.2 exports 屬性

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中可以調用。

2.3 模塊標識

模塊標識就是傳遞給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

相關文章
相關標籤/搜索