nodejs模塊中exports和module.exports的區別


 通過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不起作用了。

 

 

文章是學習筆記,如有錯誤,望指正

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM