寫在前面:
一個檔案就是一個模組。
另外本文中的示例程式碼需要在node.js環境中方可正常執行,否則將出現錯誤。事實上ES6已經出現了模組規範,如果使用ES6的模組規範是無需node.js環境的。因此,需要將commonJS規範和ES6的模組規範區分開來。
一、為什麼制定CommonJS規範?
為了在伺服器端和桌面環境中構建js的生態系統而產生的規範,是一種同步載入機制,commonjs規範的主要內容是模組必須通過 module.exports
匯出對外的變數或介面,通過 require()
來匯入其他模組的輸出到當前模組作用域中。
在後端,JavaScript的規範遠遠落後並且有很多缺陷,這使得難以使用JavaScript開發大型應用。比如:
- 沒有模組系統
- 標準庫較少
- 沒有標準介面
- 缺乏包管理系統
列表內容
CommonJS規範的提出,主要是為了彌補JavaScript沒有標準的缺陷,已達到像Python、Ruby和Java那樣具備開發大型應用的基礎能力,而不是停留在開發瀏覽器端小指令碼程式的階段。
二、CommonJS模組規範
CommonJS模組規範主要分為三部分:模組引用、模組定義、模組標識。
1、模組引用
如果在a.js檔案中使用如下語句
var math=require('math');1複製程式碼
意為使用require()方法,引入math模組,並賦值給變數math。事實上,命名的變數名和引入的模組名不必相同,就像這樣:
var Math=require('math');1複製程式碼
賦值的意義在於,a.js中將僅能識別Math,因為這是已經定義的變數,並不能識別math,因為math沒有定義。
帶路徑和不帶路徑
上面例子中require的引數僅僅是模組名字的字串,沒有帶有路徑,引用的是a.js所在當前目錄下的node_modules目錄下的math模組。如果當前目錄沒有node_modules目錄或者node_modules目錄裡面沒有安裝math模組,便會報錯。
如果要引入的模組在其他路徑,就需要使用到相對路徑或者絕對路徑,例如:
var add=require('./add.js')1複製程式碼
上面例子中引入了當前目錄下的add.js檔案,並賦值給add變數。
2、模組定義
module物件:在每一個模組中,module物件代表該模組自身。
export屬性:module物件的一個屬性,它向外提供介面。12複製程式碼
仍然採用上一個示例,假設add.js中的程式碼如下:
function add(num1,num2){
alert(num1+num2);
}123複製程式碼
儘管a.js檔案引入了add.js檔案,前者卻仍然無法使用後者中的add函式,在a.js檔案中add(3,5)
這樣的程式碼會報錯,提示add不是一個函式。
add.js中的函式要能被其他模組使用,就需要暴露一個對外的介面,export屬性用於完成這一工作。將add.js中程式碼改為如下:
exports.add=function (num1,num2){
alert(num1+num2);
}123複製程式碼
a.js檔案就可以正常呼叫add.js中的方法,例如add.add(3,5)
這樣的呼叫能夠正常執行,前一個add意為本檔案中add變數代表的模組,後一個add是引入模組的add方法。
3、模組標識
模組標識指的是傳遞給require方法的引數,必須是符合小駝峰命名的字串,或者以 . 、.. 、開頭的相對路徑,或者絕對路徑。
三、CommonJS模組規範的好處
CommonJS模組規範很好地解決變數汙染問題,每個模組具有獨立空間,互不干擾,名稱空間等方案與之相比相形見絀。
CommonJS規範定義模組十分簡單,介面十分簡潔。
CommonJS模組規範支援引入和匯出功能,這樣可以順暢地連線各個模組,實現彼此間的依賴關係。