每一個node.js執行文件,都自動創建一個module對象,同時,module對象會創建一個叫exports的屬性,初始化的值是 {}
module.exports = {};
exports和module.exports指向同一塊內存,但require()返回的是module.exports而不是exports。
var str = "difference"
exports.a = str;
exports.b = function () {
}
給 exports 賦值其實是給 module.exports 這個空對象添加了兩個屬性而已,上面的代碼相當於:
var str = "difference"
module.exports.a = str;
module.exports.b = function () {
}
來看下exports和module.exports的使用
使用exports
app.js
var s = require("./log");
s.log("hello");
log.js
exports.log =function (str) {
console.log(str);
}
用module.exports
app.js
var s = require("./log");
s.log("hello");
log.js
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的關係可以總結爲
- module.exports 初始值爲一個空對象 {},所以 exports 初始值也是 {}
- exports 是指向的 module.exports 的引用
- require() 返回的是 module.exports 而不是 exports