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

經過Node.js的官方API能夠看到Node.js自己提供了不少核心模塊 http://nodejs.org/api/ ,這些核心模塊被編譯成二進制文件,能夠require('模塊名')去獲取;核心模塊具備最高的加載優先級(有模塊與核心模塊同名時會體現),如:node

var fs=require('fs');
var http=require('http')

文件模塊訪問方式經過require('/文件名.後綴') require('./文件名.後綴') requrie('../文件名.後綴') 去訪問,文件後綴能夠省略;以"/"開頭是以絕對路徑去加載,以"./"開頭和以"../"開頭表示以相對路徑加載,而以"./"開頭表示同級目錄下文件,如:api

var myadd=require('./add');   //本目錄下的add.js

exports和module.exports;提供了外部訪問的接口緩存

(本文講exports和module.exports,是對外暴露文件,再引用,屬於文件模塊。核心模塊由node寫好,直接引用就行)
講講他們的區別
一、模塊導入會緩存,寫了屢次導入,只會導一次。
即便導入的路徑不同。它緩存是指實際文件名,並不會由於傳入的路徑形式不同而認會是不一樣的文件函數

var outputVal  = 0;     //輸出值
var increment = 1;    //增量
/* 設置輸出值 */
function seOutputVal (val) {
    outputVal = val;
}
/* 設置增量 */
function setIncrement(incrementVal){
    increment = incrementVal;
}
/* 輸出 */
function printNextCount()
{
    outputVal += increment;
    console.log(outputVal) ;
}
function printOutputVal() {
    console.log(outputVal);
}
exports.seOutputVal = seOutputVal;
exports.setIncrement = setIncrement;
module.exports.printNextCount = printNextCount;

一個Node.js文件就是一個模塊,這個文件多是Javascript代碼、JSON或者編譯過的C/C++擴展。重要的兩個對象:require是從外部獲取模塊,exports是把模塊接口公開工具

var counter = require('./1_modules_custom_counter'); 
console.log('第一次調用模塊[1_modules_custom_counter]'); 
counter.seOutputVal(10);//設置從10開始計數 
counter.setIncrement (10);//設置增量爲10 
counter.printNextCount();
counter.printNextCount();
counter.printNextCount();
counter.printNextCount();//require屢次調用同一模塊不會重複加載 
var counter = require('./1_modules_custom_counter');
console.log('第二次調用模塊[1_modules_custom_counter]');
counter.printNextCount();

clipboard.png

二、經過exports和module.exports對外公開的方法均可以訪問,但有區別ui

module.exports纔是真正的接口,exports只不過是它的一個輔助工具。 最終返回給調用的是module.exports而不是exports。
全部的exports收集到的屬性和方法,都賦值給了Module.exports。固然,這有個前提,就是module.exports自己不具有任何屬性和方法。
若是,module.exports已經具有一些屬性和方法,那麼exports收集來的信息將被忽略。this

我把exports和 module.exports都打印出來看看究竟spa

① (雖然這樣在引入模塊時會報錯,但這一步能說明問題,後面說緣由)3d

var counter  = 0;
exports.temp  = function(){
    counter += 10;
    this.printNextCount = function()
    {
        console.log(counter);
    }
}
var isEq = (exports === module.exports);
console.log(exports);
console.log(module.exports);
console.log(isEq);

結果:code

clipboard.png

經過exports導出的方法,會傳遞給module.exports。兩者沒區別

var counter  = 0;
module.exports = function(){
    counter += 10;
    this.printNextCount = function()
    {
        console.log(counter);
    }
}
var isEq = (exports === module.exports);
console.log(exports);
console.log(module.exports);
console.log(isEq);

結果:

clipboard.png

直接傳給module.exports,那exports就說明都沒有,兩者不相等了。

③:注意,導入時有點區別。和上面第一大點不同

如這裏的②

var  Counter = require('./  ');
var  counterObj = new Counter();
counterObj.printNextCount();

而第一大點能夠直接這樣:

var counter = require('./1_modules_custom_counter');
console.log('第二次調用模塊[1_modules_custom_counter]');
counter.printNextCount();

就是要new一個對象!

由於導出的文件中的函數變成了成員方法,因此要new一個對象,再調用成員方法。

說明①不可行的緣由:當我在別的文件調用它時,不管是直接調用,仍是new一個對象再調用,都報錯!

因此,要遵循這兩點

1.最好別分別定義module.exports和exports

2.NodeJs開發者建議導出對象用module.exports,導出多個方法和變量用exports

三、exports和module.exports覆蓋

直接上代碼,看誰留下,誰消失

var counter  = 0;
exports.printNextCount = function()
    {
    counter+=2;
        console.log(counter);
    }
module.exports = function(){
counter+=10;
this.printNextCount=function(){
console.log(counter)
}

}
var isEq = (exports === module.exports);
console.log(exports);
console.log(module.exports);
console.log(isEq);

想一想都知道誰厲害。

引用該模塊:

①報錯,說明exports的消失了

var counter = require('./test3');
counter.printNextCount();

②留下了。

var counter = require('./test3');
var counterObj=new counter()
counterObj.printNextCount();

結果,輸出了它成功導出的對象函數值;前面兩個是兩個接口收集到的東西,最後exports的被覆蓋了

clipboard.png

exports僅僅是module.exports的一個地址引用。nodejs只會導出module.exports的指向,若是exports指向變了,那就僅僅是exports不在指向module.exports,因而不會再被導出

至關於:a和b指向同一塊內存,b是a的地址引用

var a = new Object();//a至關於module.exports
var b = a; //b至關於exports

覆蓋,也就是a已經賦值了,但b又被賦了別的值。這時候,b就是叛變了,就指向了一塊新的地址了。而模塊引用是要用module.exports來引用,因此指向新地址的exports不起做用了。

相關文章
相關標籤/搜索