node-學習之路02 commonJS模塊
1.commonjs 模塊管理
所有代碼都運行在模塊作用域,不會汙染全局作用域。
模塊可以多次加載,但是只會在第一次加載時運行一次,然後運行結果就被緩存了,以後再加載,就直接讀取緩存結果。要想讓模塊再次運行,必須清除緩存。
模塊加載的順序,按照其在代碼中出現的順序。
2.module對象
2.1 module.exports屬性
module.exports屬性表示當前模塊對外輸出的接口,其他文件加載該模塊,實際上就是讀取module.exports變量。
2.2 exports變量
為了方便,Node為每個模塊提供一個exports變量,指向module.exports。這等同在每個模塊頭部,有一行這樣的命令:
var exports = module.exports;(commonJS隱式做了這個賦值)
2.3 js文件就是一個函數
console.log(arguments) { ‘0‘: {}, ‘1‘: { [Function: require] resolve: { [Function: resolve] paths: [Function: paths] }, main: Module { id: ‘.‘, exports: {}, parent: null, filename:‘C:\\Users\\liang\\Desktop\\node\\hello.js‘, loaded: false, children: [], paths: [Array] }, extensions: { ‘.js‘: [Function], ‘.json‘: [Function], ‘.node‘: [Function] }, cache: { ‘C:\Users\liang\Desktop\node\hello.js‘: [Object] } }, ‘2‘: Module { id: ‘.‘, exports: {}, parent:null, filename: ‘C:\\Users\\liang\\Desktop\\node\\hello.js‘, loaded: false, children: [], paths: [ ‘C:\\Users\\liang\\Desktop\\node\\node_modules‘, ‘C:\\Users\\liang\\Desktop\\node_modules‘, ‘C:\\Users\\liang\\node_modules‘, ‘C:\\Users\\node_modules‘, ‘C:\\node_modules‘ ] }, ‘3‘: ‘C:\\Users\\liang\\Desktop\\node\\hello.js‘, ‘4‘: ‘C:\\Users\\liang\\Desktop\\node‘ }
console.log(arguments.callee)
[Function]
console.log(arguments.length)
5
(function (exports, require, module, __filename, __dirname){})()
exports是module.exports的一個引用
require引用模塊後,返回給調用者的是module.exports而不是exports
exports.xxx,相當於在導出對象上掛屬性,該屬性對調用模塊直接可見
exports =相當於給exports對象重新賦值,調用模塊不能訪問exports對象及其屬性
如果此模塊是一個類,就應該直接賦值module.exports,這樣調用者就是一個類構造器,可以直接new實例
這是兩種暴漏的方式,都可以使用
下面是引入方式,及結果
我們可以看成 exports = module.exports = {} 就是exports 指針指向module.exports的對象
關於rfequire 引入的返回值是module.exports
2.4 require 規則
(1)如果參數字符串以“/”開頭,則表示加載的是一個位於絕對路徑的模塊文件。比如,require(‘/home/marco/foo.js‘)將加載/home/marco/foo.js。
(2)如果參數字符串以“./”開頭,則表示加載的是一個位於相對路徑(跟當前執行腳本的位置相比)的模塊文件。比如,require(‘./circle‘)將加載當前腳本同一目錄的circle.js。
(3)如果參數字符串不以“./“或”/“開頭,則表示加載的是一個默認提供的核心模塊(位於Node的系統安裝目錄中),或者一個位於各級node_modules目錄的已安裝模塊(全局安裝或局部安裝)
(4)如果參數字符串不以“./“或”/“開頭,而且是一個路徑,比如require(‘example-module/path/to/file‘),則將先找到example-module的位置,然後再以它為參數,找到後續路徑。
(5)如果指定的模塊文件沒有發現,Node會嘗試為文件名添加.js、.json、.node後,再去搜索。.js件會以文本格式的JavaScript腳本文件解析,.json文件會以JSON格式的文本文件解析,.node文件會以編譯後的二進制文件解析。
(6)如果想得到require命令加載的確切文件名,使用require.resolve()方法。
2.5模塊緩存
第一次加載某個模塊時,Node會緩存該模塊。以後再加載該模塊,就直接從緩存取出該模塊的module.exports屬性。
require(‘./example.js‘);require(‘./example.js‘).message = "hello";require(‘./example.js‘).message// "hello"
上面代碼中,連續三次使用require命令,加載同一個模塊。第二次加載的時候,為輸出的對象添加了一個message屬性。但是第三次加載的時候,這個message屬性依然存在,這就證明require命令並沒有重新加載模塊文件,而是輸出了緩存。
如果想要多次執行某個模塊,可以讓該模塊輸出一個函數,然後每次require這個模塊的時候,重新執行一下輸出的函數。
所有緩存的模塊保存在require.cache之中,如果想刪除模塊的緩存,可以像下面這樣寫。
2.6require.main
require.main === module// true
node-學習之路02 commonJS模塊