淺析Node模組中module.exports與exports的關係

weixin_34162695發表於2018-06-06

Node.js遵循CommonJS規範的模組機制,一個JS檔案即被視為一個獨立的模組。在模組內部可以通過2種方式匯出模組:

  1. module.exports
  2. exports

module.exports是一個物件引用,這個物件具有以下特徵:

  1. 預設值:{}
  2. 模組始終匯出該物件

exports也是一個物件引用,它與module.exports預設指向同一個物件

console.log(module.exports === exports);	// true
複製程式碼

所以如果我們只是向module.exports(或exports)追加需要匯出的內容時,採用哪種方式都可以,因為兩者始終指向同一個物件

module.exports.a = 1;

console.log(module.exports);	// { a: 1 }
console.log(exports);			// { a: 1 }

exports.b = 2;
console.log(module.exports);	// { a: 1, b: 2 }
console.log(exports);			// { a: 1, b: 2 }
複製程式碼

但如果給module.exports(或exports)重新賦值,那麼就會出現一些意想不到的效果。假設我們使用如下的方式匯出模組

// foo.js
module.exports = {
	a: 1
}
exports.b = 2;
複製程式碼
// main.js
var foo = require('./foo');

console.log(foo);	// { a: 1 },匯出的物件並不包含b
複製程式碼

出現上面結果的原因是:module.exports在被’=’賦值時,實際上是新生成了一個{a: 1}物件,並且斷開module.exports與預設物件{}的引用,從而指向{a: 1}這個新生成的物件;然而exports此時還是指向預設物件{}exports.b = 2;實際上是向這個預設物件新增了b,而不是module.exports所指的那個物件;並且Node模組最終只會匯出module.exports所指向的那個物件(或值),所以就出現了上面的結果。

概括一句話就是:給模組物件的重新複製導致module.exports與exports分別指向了不同的物件

‘最好的證明就是用程式碼演示’,所以我們程式碼證明一下上面的分析

// foo.js
module.exports = {
  a: 1
}
exports.b = 2;

console.log(module.exports === exports);	// false
console.log(module.exports);				// { a: 1 }
console.log(exports);						// { b: 2 }
複製程式碼
// main.js
var foo = require('./foo');

console.log(foo);	// { a: 1 }
複製程式碼

那麼是否有辦法修補上面的問題呢?答案是:有的,問題的關鍵是:module.exports與exports指向了不同的物件,那麼我們就將它們指回同一個物件

// foo.js
module.exports = {
  a: 1
}

console.log(module.exports === exports);	// false

exports = module.exports;
exports.b = 2;

console.log(module.exports === exports);	// true
console.log(module.exports);				// { a: 1, b: 2 }
console.log(exports);						// { a: 1, b: 2 }
複製程式碼

所以,匯出模組時我們最好採用如下形式:

exports = module.exports = {
	a: 1
}

console.log(module.exports === exports);	// true
console.log(module.exports);				// { a: 1 }
console.log(exports);						// { a: 1 }
複製程式碼

以上就是對module.exports與exports兩者關係的淺顯分析,希望對大家有所幫助,如有錯誤,歡迎指正~

原文地址:www.guoyunfeng.com/2018/06/06/…

相關文章