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
对象上,不要和导出属性值混在一起