CommonJS規範
文章目錄
1.概述
Node 應用由模塊組成,採用 CommonJS 模塊規範。
每個文件就是一個模塊,有自己的作用域,在一個文件裏面定義的變量,函數,類,都是私有的,對其他文件不可見.
CommonJS規範規定,每個模塊內部,module變量代表當前模塊,這個變量是一個對象,它的exports屬性(module.exports)是對外的接口,加載某個模塊,其實就是加載該模塊的module.exports屬性
require方法用於加載模塊
CommonJS模塊特點如下:
1.所有代碼都運行在模塊作用域,不會污染全局作用域
2.模塊可以多次加載,但是隻會在第一次加載時運行一次,然後運行結果就被緩存了,以後 再加載,就直接讀取緩存結果,要想讓模塊再次運行,必須清除緩存
3.模塊加載順序,按照其在代碼中出現的順序.
4.模塊加載是同步的,也就是說只有加載完成,才能執行後面的操作
2.module對象
每個模塊內部,都有一個module對象,代表當前模塊,它有以下屬性:
-
module.id 模塊的識別符,通常是帶有絕對路徑的模塊文件名
-
module.filename 模塊的文件名,帶有絕對路徑
-
module.loaded 返回一個布爾值,表示模塊是否已經完成加載
-
module.parent 返回一個對象,表示調用該模塊的模塊
-
module.children 返回一個數組,表示該模塊要用到的其他模塊
-
module.exports 表示對外輸出的值
我們在當前一個js中直接輸出console.log(module);會輸出這樣一個module對象.
{ id: '.', exports: { '$': [Function] }, parent: null, filename: '/path/to/index.js', loaded: false, children: [ { id: '/path/to/node_modules/jquery/dist/jquery.js', exports: [Function], parent: [Circular], filename: '/path/to/node_modules/jquery/dist/jquery.js', loaded: true, children: [], paths: [Object] } ], paths: [ '/home/user/deleted/node_modules', '/home/user/node_modules', '/home/node_modules', '/node_modules' ] }
module.exports
module.exports屬性表示當前模塊對外輸出的接口,其他文件加載該模塊,實際上是讀取module.exports
//idnex.js
var num=3;
function add(a,b){
return a+b;
}
module.exports={
add:add
}
//此處輸出跟上面效果一樣,這是es6,對象的簡寫,key,value一致,可以只寫一個
moudle.exports={
add
}
//這種方式也是可以的
module.exports.add=add;//暴露方法
module.exports.num=num;//暴露變量
//在同目錄下的main.js 中
var example=require('./index');
example.add(1,2); //3
exports變量
每個模塊化還提供一個exports變量,指向module.exports,這就等於在每個模塊頭部,都有一行隱藏的如下代碼
var exports=module.exports;
例如: exports.show=function(){console.log(123)}
注意:不能把exports直接指向一個值,這樣就相當於切斷了exports和module.exports的關係
例如:exports=10;
如果你覺得,exports與module.exports之間的區別很難分清,一個簡單的處理方法,就是放棄使用exports,只使用module.exports
3.AMD規範與CommonJS規範的兼容性
CommonJS規範加載模塊是同步的,也就是說,只有加載完成,才能執行後面的操作。AMD規範則是非同步加載模塊,允許指定回調函數。由於Node.js主要用於服務器編程,模塊文件一般都已經存在於本地硬盤,所以加載起來比較快,不用考慮非同步加載的方式,所以CommonJS規範比較適用。但是,如果是瀏覽器環境,要從服務器端加載模塊,這時就必須採用非同步模式,因此瀏覽器端一般採用AMD規範。
4.require命令
1.基本用法
require命令的基本功能是,讀入並執行一個javascript文件,然後返回該模塊的module,exports對象,如果發現沒有指定模塊,會報錯.
2.加載規則
- 後綴名默認爲.js
var show=require('show')
//等同於
var show=require('show.js')
//.js可以省略
-
如果參數字符串以“/”開頭(linux)或者以 “D:/”盤符開頭(windows),則表示加載的是一個位於絕對路徑的模塊文件。比如,require(’/home/marco/foo.js’) 將加載 /home/marco/foo.js
-
如果參數字符串以“./”開頭,則表示加載的是一個位於相對路徑(跟當前執行腳本的位置相比)的模塊文件。比如,require(’./circle’) 將加載當前腳本同一目錄的 circle.js
-
如果參數字符串不以“./“或”/“開頭,則表示加載的是一個默認提供的核心模塊(位於Node的系統安裝目錄中),或者一個位於各級node_modules目錄的已安裝模塊(全局安裝或局部安裝)。
-
如果參數字符串不以“./“或”/“開頭,而且是一個路徑,比如 require(‘example-module/path/to/file’),則將先找到 example-module 的位置,然後再以它爲參數,找到後續路徑。
-
如果指定的模塊文件沒有發現,Node會嘗試爲文件名添加**.js、.json、.node**後,再去搜索。.js件會以文本格式的JavaScript腳本文件解析,.json文件會以JSON格式的文本文件解析,.node文件會以編譯後的二進制文件解析。
3.目錄的加載規則
通常,我們會把相關的文件會放在一個目錄裏面,便於組織。這時,最好爲該目錄設置一個入口文件,讓 require 方法可以通過這個入口文件,加載整個目錄。
在目錄中放置一個 package.json 文件,並且將入口文件寫入 main 字段。下面是一個例子。
// package.json
{
"name" : "some-library",
"main" : "./lib/some-library.js"
}
require 發現參數字符串指向一個目錄以後,會自動查看該目錄的 package.json 文件,然後加載 main 字段指定的入口文件。如果 package.json 文件沒有 main 字段,或者根本就沒有 package.json 文件,則會加載該目錄下的index.js 文件 或者 index.json 文件 或者 index.node 文件。
4.模塊的加載機制
CommonJS模塊的加載機制是:輸出拷貝,也就是說,一旦輸出一個值,模塊內部的變化就影響不到這個值,上代碼瞭解一下:
//index.js
var num=1;
function add(){
num++;
}
module.exports={
num:num,
add:add
}
現在呢,我們引入這個index.js
//main.js
var num=require("./index").num;
var add=require("./index").add;
console.log(num);//3
add();
console.log(num);//3
上述代碼說明,num輸出以後,index.js模塊內部的變化不會影響到咱們這邊調用時的num了
此文參考阮一峯大神文章