每個node.js執行文件,都自動建立一個module對象,同時,module對象會建立一個叫exports的屬性,初始化的值是 {}node
module.exports = {};
exports和module.exports指向同一塊內存,但require()返回的是module.exports而不是exports。app
var str = "difference" exports.a = str; exports.b = function () { }
給 exports 賦值實際上是給 module.exports 這個空對象添加了兩個屬性而已,上面的代碼至關於:ui
var str = "difference" module.exports.a = str; module.exports.b = function () { }
來看下exports和module.exports的使用code
使用exports對象
app.js內存
var s = require("./log"); s.log("hello");
log.jsit
exports.log =function (str) { console.log(str); }
用module.exportsio
app.jsconsole
var s = require("./log"); s.log("hello");
log.jsfunction
module.exports =function (str) { console.log(str); }
述兩種用法都沒問題,但若是這樣使用
exports = function (str) { console.log(str); }
行程序就會報錯。
前面的例子中給 exports 添加屬性,只是對 exports 指向的內存作了修改。而上例則是對exports指向的內存進行了覆蓋,使exports指向了一塊新的內存,這樣,exports和module.exports指向的內存並非同一塊,exports和module.exports並沒有任何關係。exports指向的內存有了變化,而module.exports指向的內存並沒有變化,仍爲空對象{}。
require獲得的會是一個空對象,則會有
TypeError: s.log is not a function
報錯信息。
再看下面的例子
app.js
var x = require('./init'); console.log(x.a)
init.js
module.exports = {a: 2} exports.a = 1
運行app.js會有輸出
2
這也就是module.exports對象不爲空的時候exports對象就自動忽略,由於module.exports經過賦值方式已經和exports對象指向的變量不一樣了,exports對象怎麼改和module.exports對象不要緊了。
exports = module.exports = somethings
等價於
module.exports = somethings exports = module.exports
緣由也很簡單, module.exports = somethings 是對 module.exports 進行了覆蓋,此時 module.exports 和 exports 的關係斷裂,module.exports 指向了新的內存塊,而 exports 仍是指向原來的內存塊,爲了讓 module.exports 和 exports 仍是指向同一塊內存或者說指向同一個 「對象」,因此咱們就 exports = module.exports 。
最後,關於exports和module.exports的關係能夠總結爲