通過Node.js的官方API可以看到Node.js本身提供了很多核心模塊 http://nodejs.org/api/ ,這些核心模塊被編譯成二進制文件,可以require('模塊名')去獲取;核心模塊具有最高的加載優先級(有模塊與核心模塊同名時會體現),如:
var fs=require('fs'); var http=require('http')
文件模塊訪問方式通過require('/文件名.后綴') require('./文件名.后綴') requrie('../文件名.后綴') 去訪問,文件后綴可以省略;以"/"開頭是以絕對路徑去加載,以"./"開頭和以"../"開頭表示以相對路徑加載,而以"./"開頭表示同級目錄下文件,如:
var myadd=require('./add'); //本目錄下的add.js
exports和module.exports;提供了外部訪問的接口
(本文講exports和module.exports,是對外暴露文件,再引用,屬於文件模塊。核心模塊由node寫好,直接引用就行)
講講他們的區別
1、模塊導入會緩存,寫了多次導入,只會導一次。
即使導入的路徑不一樣。它緩存是指實際文件名,並不會因為傳入的路徑形式不一樣而認會是不同的文件
1 var outputVal = 0; //輸出值 2 var increment = 1; //增量 3 /* 設置輸出值 */ 4 function seOutputVal (val) { 5 outputVal = val; 6 } 7 /* 設置增量 */ 8 function setIncrement(incrementVal){ 9 increment = incrementVal; 10 } 11 /* 輸出 */ 12 function printNextCount() 13 { 14 outputVal += increment; 15 console.log(outputVal) ; 16 } 17 function printOutputVal() { 18 console.log(outputVal); 19 } 20 exports.seOutputVal = seOutputVal; 21 exports.setIncrement = setIncrement; 22 module.exports.printNextCount = printNextCount;
1 /* 2 一個Node.js文件就是一個模塊,這個文件可能是Javascript代碼、JSON或者編譯過的C/C++擴展。 3 重要的兩個對象: 4 require是從外部獲取模塊 5 exports是把模塊接口公開 6 */ 7 var counter = require('./1_modules_custom_counter'); 8 console.log('第一次調用模塊[1_modules_custom_counter]'); 9 counter.seOutputVal(10); //設置從10開始計數 10 counter.setIncrement (10); //設置增量為10 11 counter.printNextCount(); 12 counter.printNextCount(); 13 counter.printNextCount(); 14 counter.printNextCount(); 15 /* 16 require多次調用同一模塊不會重復加載 17 */ 18 var counter = require('./1_modules_custom_counter'); 19 console.log('第二次調用模塊[1_modules_custom_counter]'); 20 counter.printNextCount();

2、通過exports和module.exports對外公開的方法都可以訪問,但有區別
module.exports才是真正的接口,exports只不過是它的一個輔助工具。 最終返回給調用的是module.exports而不是exports。
所有的exports收集到的屬性和方法,都賦值給了Module.exports。當然,這有個前提,就是module.exports本身不具備任何屬性和方法。
如果,module.exports已經具備一些屬性和方法,那么exports收集來的信息將被忽略。
我把exports和 module.exports都打印出來看看究竟
① (雖然這樣在引入模塊時會報錯,但這一步能說明問題,后面說原因)
1 var counter = 0; 2 exports.temp = function(){ 3 counter += 10; 4 this.printNextCount = function() 5 { 6 console.log(counter); 7 } 8 } 9 var isEq = (exports === module.exports); 10 console.log(exports); 11 console.log(module.exports); 12 console.log(isEq);
結果:

通過exports導出的方法,會傳遞給module.exports。二者沒區別
②
1 var counter = 0; 2 module.exports = function(){ 3 counter += 10; 4 this.printNextCount = function() 5 { 6 console.log(counter); 7 } 8 } 9 var isEq = (exports === module.exports); 10 console.log(exports); 11 console.log(module.exports); 12 console.log(isEq);
結果:

直接傳給module.exports,那exports就說明都沒有,二者不相等了。
③:注意,導入時有點區別。和上面第一大點不一樣
如這里的②
1 var Counter = require('./ '); 2 var counterObj = new Counter(); 3 counterObj.printNextCount();
而第一大點可以直接這樣:
1 var counter = require('./1_modules_custom_counter'); 2 console.log('第二次調用模塊[1_modules_custom_counter]'); 3 counter.printNextCount();
就是要new一個對象!
因為導出的文件中的函數變成了成員方法,所以要new一個對象,再調用成員方法。
說明①不可行的原因:當我在別的文件調用它時,無論是直接調用,還是new一個對象再調用,都報錯!
所以,要遵循這兩點
1.最好別分別定義module.exports和exports
2.NodeJs開發者建議導出對象用module.exports,導出多個方法和變量用exports
3、exports和module.exports覆蓋
直接上代碼,看誰留下,誰消失
1 var counter = 0; 2 exports.printNextCount = function() 3 { 4 counter+=2; 5 console.log(counter); 6 } 7 module.exports = function(){ 8 counter+=10; 9 this.printNextCount=function(){ 10 console.log(counter) 11 } 12 13 } 14 var isEq = (exports === module.exports); 15 console.log(exports); 16 console.log(module.exports); 17 console.log(isEq);
想想都知道誰厲害。
引用該模塊:
①報錯,說明exports的消失了
1 var counter = require('./test3'); 2 counter.printNextCount();
②留下了。
1 var counter = require('./test3'); 2 var counterObj=new counter() 3 counterObj.printNextCount();
結果,輸出了它成功導出的對象函數值;前面兩個是兩個接口收集到的東西,最后exports的被覆蓋了

exports僅僅是module.exports的一個地址引用。nodejs只會導出module.exports的指向,如果exports指向變了,那就僅僅是exports不在指向module.exports,於是不會再被導出
相當於:a和b指向同一塊內存,b是a的地址引用
1 var a = new Object();//a相當於module.exports 2 var b = a; //b相當於exports
覆蓋,也就是a已經賦值了,但b又被賦了別的值。這時候,b就是叛變了,就指向了一塊新的地址了。
而模塊引用是要用module.exports來引用,所以指向新地址的exports不起作用了。
文章是學習筆記,如有錯誤,望指正
