Node中exports與module.export的使用與區別
module.exports與exports的介紹
module.exports與exports都是將函式或者是方法暴露出去,require的時候進行呼叫,但是2者是有區別的。以下是程式碼:
//ex.js exports='danhuangmode'; //mex.js
module.exports='danhuangmode';
//call_ex_mex.js
var ex=require('./ex');
var mex=require('./mex');
console.log(ex);
console.log('\n');
console.log(mex);
執行結果:
引用exports提供方法,輸出是為一個物件,引用module.exports提供方法,輸出為字串。
exports內部提供介面,在外部引用時之間的關係如何?
exports內部處理暴露方法,是如何處理的,看如下程式碼:
var string='this is in exports.js'; function ex_fn () { console.log('this in funtion ex_fn'); } var exobj={ str1:"str1 exobj", exobjfn: function () { console.log("in function"); } }; exports.string=string; exports.ex_fn=ex_fn; exports.exobj=exobj; exports=exobj;
呼叫程式碼:
var ex=require('./ex'); console.log(ex.string); console.log(ex.ex_fn); console.log(ex.exobj); console.log(ex);
結果顯示:
exports提供的所有介面,直接呼叫匯出例項化的介面物件,會顯示介面物件中所有提供的型別、函式、物件以及物件中的方法和物件。
module.exports對外提供介面如何處理?
//mex.js var ex_fn= function () { console.log('this in funtion ex_fn'); } module.exports=ex_fn;
呼叫程式碼mex.js:
//引用mex.js
var ex=require('./mex');
ex();
console.log(ex);
執行結果為:
直接將函式作為返回。
再看下面一個例子:
var person={ name :"person's name", age :20, getAge: function () { return this.age; } } module.exports = person;
呼叫的程式碼:
var person=require('./modulex'); console.log(person.name); console.log(person.age); console.log(person.getAge()); console.log(person);
顯示的結果為:
返回為一個json物件,可以直接呼叫內部的函式、屬性。
module.exports 與exports是什麼關係?
module.exports = 'personname'; exports.name=function () { console.log('this is person name'); }
呼叫 的指令碼:
var person=require('./person'); console.log(person); console.log(person.name);
執行結果:
personname
undefined
結果:
其實真正的介面是module.exports,exports是一個輔助工具。最終返回到是module.exports,而不是exports。
當module.exports沒有任何屬性和方法,exports將收集的所有資訊都傳遞給module.exports,如果module.exports已經具有了屬性和方法,exports所蒐集的資訊將會被忽略。
-------------------------------------------------------------------
第二種解說:
exports = module.exports = {};
所以module.exports
和exports
的區別就是var a={}; var b=a;
,a和b的區別
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.exports
和exports
混用是完全可以的,這種情況下,感覺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.exports
和exports
的區別就是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
物件上,不要和匯出屬性值混在一起