在學習NodeJS的過程中,module是結構化程式基本的組塊。
我們能藉由module將各function block分開來,並且在主程式引用其method或property
然而,要使用module的method或property有許多方式,本文整理常用的幾種並說明特性。
Module基本使用方式
假設我們有二個js程式:app.js和greet.js,想要讓app.js使用greet.js的method,則需要使用module
greet.js1 2 3 4 5
   | var greet = function() { 	console.log('Hello'); }
  module.exports = greet;
  | 
 
app.js1 2
   | var greet = require('./greet'); greet();
  | 
 
要在app.js使用greet.js的greet方法,得先require greet.js
require預設是引入javascript檔案,所以副檔名可省略。
而greet.js中,將greet這個函式變數設為module.exports的參考
module.exports其實是個object,供其它js檔案使用其method
上述的寫法可以簡化為:
greet.js1 2 3
   | module.exports = function() { 	console.log('Hello'); }
  | 
 
app.js1 2
   | var greet = require('./greet'); greet();
  | 
 
也是一樣的結果
使用Function Expression
greet2.js1 2 3
   | module.exports.greet = function() {     console.log('Hello World'); }
  | 
 
app.js1 2
   | var greet2 = require('./greet2').greet; greet2();
  | 
 
利用function expression讓module.exports多一個method
使用Function Constructor
greet3.js1 2 3 4 5 6 7 8
   | function Greetr() { 	this.greeting = 'Hello world!!'; 	this.greet = function() { 		console.log(this.greeting); 	} }
  module.exports = new Greetr();
  | 
 
app.js1 2
   | var greet3 = require('./greet3'); greet3.greet();
  | 
 
使用function constructor建立object,並利用this存取function
module.exports則指向新的function constructor
此例有個需要注意的地方,假如我在app.js改變greeting的值,會發生什麼事??
app.js1 2 3 4 5
   | var greet3 = require('./greet3'); greet3.greeting = 'Changed';
  var greet3b = require('./greet3'); greet3b.greet();
  | 
 
改變greeting的值以後,我們再require greet3並且呼叫method,則結果如下:
1 2
   | > Hello world!! > Changed
   | 
這裡帶出一個module重要的特性:NodeJs的核心會cache同一個module的參考,所以當我們宣告greet3b為greet3的object時,其實底層是回傳上一個greet3的參考,而此時greeting己被改變。
所以在不同的js檔案使用同一個module時,需注意其實回傳的都是同一份copy
Function Constructor變形
greet4.js1 2 3 4 5 6 7 8
   | function Greetr() { 	this.greeting = 'Hello world!!!'; 	this.greet = function() { 		console.log(this.greeting); 	} }
  module.exports = Greetr;
  | 
 
app.js1 2 3
   | var greet4 = require('./greet4'); var greetr = new greet4(); greetr.greet();
  | 
 
這種方式把建構子放在app.js,所以不會有二個require指向同一份copy
Revealing Module Pattern
greet5.js1 2 3 4 5 6 7 8 9
   | var greeting = 'Hello JS!';   function greet() { 	console.log(greeting); }
  module.exports = { 	greet: greet }
   | 
 
app.js1 2
   | var greet5 = require('./greet5').greet; greet5();
  | 
 
這裡我們使用object並把greet指向greet methond,所以module.exports只能存取greet而不會改到其它值
這種方式也稱為Revealing Module Pattern,在javascript中是常用的包裝方式。
以上為NodeJS使用module.exports的幾種方式。