node.js中module.export與export的區別。


對module.exports和exports的一些理解

可能是有史以來最簡單通俗易懂的有關Module.exports和exports區別的文章了。

exports = module.exports = {};

所以module.exportsexports的區別就是var a={}; var b=a;,a和b的區別

看起來木有什么太大區別,但實際用起來的時候卻又有區別,這是為啥呢,請聽我細細道來

關於Module.exports和exports有什么區別,網上一搜一大把,但是說的都太復雜了…
聽說exports是Module.exports對象的一個引用(reference)^1,什么是引用?!…_(:з」∠)_

當然啦,如果要徹底理解這兩個導出的區別,最好肯定是去看源碼,看看都是怎么封裝的,功力深厚的童鞋應該一看就懂了。不過,源碼我也是看不懂的…(ಥ_ಥ)

但是最近感覺雜七雜八看了好多文章做了好多實驗之后,像是打開了任督二脈,機智的我好像有點上道了…

module

首先要明確的一點,module是一個對象 {Object}
當你新建一個文件,比如mo.js,文件內容如下:

1
console.log(module);

 

然后在CMD里執行這個文件node mo.js,就能看到module其實是一個Module實例,你可以這么理解,NodeJS中定義了一個Module類,這個類中有很多屬性和方法,exports是其中的一個屬性:

1
2
3
4
5
function Module {
id : 'blabla',
exports : {},
blabla...
}

 

當每個js文件在執行或被require的時候,NodeJS其實創建了一個新的實例var module = new Module(),這個實例名叫module
這也就是為什么你並沒有定義module這個變量,卻能console.log出來而不會報錯的原因

module.exports

假設我有一個JS文件內容如下:

console.log(module); //你會看到Module中的exports為空對象{} module.exports = { print : function(){console.log(12345)} } console.log(module); //你會看到Module中的exports對象已經有了print()方法 

有了上面的基礎,很容易理解module.export其實是給Module實例中的exports對象中添加方法/屬性

exports

通常使用exports的時候,是這么用的:

exports.print = function(){console.log(12345)} 

假設我有一個JS文件內容如下:

console.log(module); //你會看到Module中的exports為空對象{} console.log(exports); //你會看到Module中的exports為空對象{} module.exports = { print : function(){console.log(12345)} } console.log(module); //你會看到Module中的exports對象有了print()方法 exports.name = '小白妹妹'; console.log(module); //你會看到Module中的exports對象不僅有了print()方法,還有了name屬性 

由此也能看出,傳說中的exports其實是module.exports的引用,你可以這么理解,NodeJS在你的代碼之前悄悄的加了以下代碼:

var module = new Module();
var exports = module.exports;

這也就是為什么你並沒有定義exports這個變量,卻能console.log出來而不會報錯的原因

require

當你從外部調用某個模塊,require其實是在require什么?^2
require的時候NodeJS會到處去找有沒有這個模塊,如果有,return的就是module.exports里的東東。

DOs & DONTs

  • √你可以這樣:
    module.exports.name = '小白妹妹';
    exports.age = 10;
    module.exports.print = function(){console.log(12345)};
    
    如果只是使用.來添加屬性和方法,module.exportsexports混用是完全可以的,這種情況下,感覺exports就是給懶人用的…畢竟能少寫幾個7個字符呢!
  • √也可以這樣:
    module.exports = {
    name = '小白妹妹';
    };
    exports.age = 10;
    module.exports.print = function(){console.log(12345)};
    
  • ×但不可以這樣
    module.exports = {
    name = '小白妹妹';
    };
    exports = {age:10}; // exports現在是{age:10}這個對象的引用,不再是module.exports的引用了
    console.log(module); //你會看到Module的exports中只有name屬性!!!
    
  • ×也不可以這樣
    exports.age = 10; 
    console.log(module); //你會看到Module的exports中多了age屬性
    module.exports = {
    name = '小白妹妹';
    };
    console.log(module); //你會看到Module的exports中還是只有name屬性!!!
    

    總結

    還是那一句話,module.exportsexports的區別就是var a={}; var b=a;,a和b的區別
    • 改變exports的指向后所添加的exports.xxx都是無效的。因為require返回的只會是module.exports
  • 不能在使用了exports.xxx之后,改變module.exports的指向。因為exports.xxx添加的屬性和方法並不存在於module.exports所指向的新對象中。
  • 對於要導出的屬性,可以簡單直接掛到exports對象上
  • 對於類,為了直接使導出的內容作為類的構造器可以讓調用者使用new操作符創建實例對象,應該把構造函數掛到module.exports對象上,不要和導出屬性值混在一起

感覺自己說的還是挺清楚噠~
不管你清不清楚,我反正是清楚了。_(:з」∠)_


免責聲明!

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



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