# CommonJS中的導出ide
// cal.js中導出一個對象 module.exports = { name: 'cal', add: function(a, b) { return a + b; } } // 爲了書寫方便,能夠像下面簡寫 exports.name = 'cal'; exports.add = function(a, b) { return a + b; }
上面兩段代碼,在實現效果上沒有任何的不一樣.ui
其內在機制是將exports指向了module.exports,而moudle.exports在初始化時是一個空對象.咱們能夠簡單的理解爲,CommonJS在每一個模塊的首部默認添加了如下代碼:spa
var module = { exports: {} } var exports = module.exports
所以,爲exports.add賦值,至關於在module.exports對象上添加了一個屬性對象
# 注意:blog
在使用exports時要注意一個問題,即不要直接給exports賦值,不然致使其失效,如:接口
exports = { add: function(a, b) { return a + b; } }
上面代碼中,因爲對exports進行了賦值操做,使其指向了一個新的對象,module.exports卻仍然是原來的空對象,所以add屬性並不會被導出,例以下面這個代碼:it
var module = { exports: {} } var exports = module.exports console.log(exports === module.exports) // true exports = { add: function(a, b) { return a + b } } console.log(exports === module.exports) // false 注意這個地方是false
# 注意:io
另外一個須要注意的問題,module.exports和exports不要混用console
exports.add = function(a, b) { return a + b } module.exports = { name: 'cal' }
上面代碼中的module.exports指向了另外一個對象,致使以前的add屬性被丟失,因此最後導出只有name屬性function
# 注意:
在module.exports和exports後面的代碼依舊會執行,但不建議這樣寫
# CommonJS中的導入
使用require導入模塊時,有下面兩種狀況:
1.require的模塊是第一次被加載.這時會首先執行該模塊,而後導出內容
2.require的模塊曾被加載過.這時該模塊的代碼不會再次執行,而是直接導出上次執行後的結果
例如:
// cal.js console.log('cal.js') module.exports = { name: '我是喬峯', add: function(a, b) { return a + b } } // index.js // 第一次require const add = require('./cal').add console.log(add(1, 2)) // 第二次require const name = require('./cal').name console.log(name)
此時的結果以下:
從結果上能夠看出,儘管咱們require兩次,但其內部代碼只會執行一遍.
其原理大體以下:
在模塊中,有一個module對象用來存儲信息,這個對象中有一個屬性loaded用於記錄該模塊是否被加載過.它的默認值是false,當模塊第一次被加載和執行事後會變成true
若是後面再次加載時,檢測到loaded爲true,則不會次再執行模塊代碼
# 注意:
有時咱們加載一個模塊,不須要獲取其導出的內容,只是想要經過執行它而產生某種做用,好比把它的接口掛載到全局對象上,此時直接使用require便可
require('./task.js')
# 注意:
另外,require能夠接收表達式,能夠動態加載指定的模塊
const moduleNames = ['foo.js', 'bar.js'] moduleNames.forEach(name => { require('./' + name) })