module.exports和exports的區別
module.exports和exports的區別
我們要弄明白module.exports和exports的區別,就要清楚什麼是值型別,什麼是引用型別。值型別是儲存在棧上,引用型別儲存在堆上。引用型別的名字是儲存在棧上的,這個名字指向堆上的一個地址即該引用型別所在的地址。
我們用程式碼認識一下引用型別
var p1 = {
name: 'zhangsan',
age: 18
}
var p2 = p1
console.log(p2.name) //打印出zhangsan
此時 var p1 和var p2指向同一個堆地址即兩個儲存在棧上的引用型別名稱 指向同一個引用型別,此時當我門改變p2的屬性值,p1也會跟著改變
var p1 = {
name: 'zhangsan',
age: 18
}
var p2 = p1
p2.age = 19
console.log(p1.age) //列印結果 19
其實此時儲存在棧上的變數名稱p1和p2是指向同一個堆中的物件,當我們改變物件的某個屬相。相當於兩個變數名稱指向的同一個物件改變了。
理解了上面的引用型別改變的原理之後其實就很好理解了。module
和exports
是Node.js
給每個js檔案內建的兩個物件。可以通過console.log(module.exports)
和console.log(exports)
打印出來都為一個空物件{}
實際上兩者的關係就如同上面的p1和p2的關係。module.exports和exports是指向同一個堆地址的
module.exports = exports = {}
require
引入的物件本質上是module.exports
。這就產生了一個問題,當 module.exports
和exports
指向的不是同一塊記憶體時,exports
的內容就會失效。
示例程式碼common.js :
module.exports={
sayHello:name=>{
console.log(`hello ${name}`)
}
}
exports.sayGoodbye=name=>{
console.log(`Goodbye ${name}`)
}
示例程式碼index.js :
const common =require('./common.js')
common.sayHello('xin')
common.sayGoodbye('xin') //這裡會報錯 common.sayGoodbye is not function
這裡的報錯是因為當執行common.js檔案中的module.exports={ ...}這段程式碼的時候 實際上是給module.exports重新賦值
又因為require
預設引用的是module.exports所指向的物件。所以此時exports的匯出依然已經失效。就丟擲了common.sayGoodbye is not function
的錯誤
總結:
初始狀態為module.exports = exports ={}
當exports 和module.exports指向的不是同一個堆地址時。exports失效!