详解nodejs中exports和module.exports的区别
require用来加载代码,而exports和module.exports则用来导出代码。但很多新手可能会迷惑于exports和module.exports的区别,为了更好的理解exports和module.exports的关系,我们先来巩固下js的基础。示例:
app.js
vara={name:'nswbmw1'}; varb=a; console.log(a); console.log(b); b.name='nswbmw2'; console.log(a); console.log(b); varb={name:'nswbmw3'}; console.log(a); console.log(b);
运行app.js结果为:
{name:'nswbmw1'} {name:'nswbmw1'} {name:'nswbmw2'} {name:'nswbmw2'} {name:'nswbmw2'} {name:'nswbmw3'}
解释一下:a是一个对象,b是对a的引用,即a和b指向同一个对象,即a和b指向同一块内存地址,所以前两个输出一样。当对b作修改时,即a和b指向同一块内存地址的内容发生了改变,所以a也会体现出来,所以第三、四个输出一样。当对b完全覆盖时,b就指向了一块新的内存地址(并没有对原先的内存块作修改),a还是指向原来的内存块,即a和b不再指向同一块内存,也就是说此时a和b已毫无关系,所以最后两个输出不一样。
明白了上述例子后,我们进入正题。
我们只需知道三点即可知道exports和module.exports的区别了:
- exports是指向的module.exports的引用
- module.exports初始值为一个空对象{},所以exports初始值也是{}
- require()返回的是module.exports而不是exports
所以:我们通过
varname='nswbmw'; exports.name=name; exports.sayName=function(){ console.log(name); }
给exports赋值其实是给module.exports这个空对象添加了两个属性而已,上面的代码相当于:
varname='nswbmw'; module.exports.name=name; module.exports.sayName=function(){ console.log(name); }
我们通常这样使用exports和module.exports
一个简单的例子,计算圆的面积:
使用exports
app.js
varcircle=require('./circle'); console.log(circle.area(4));
circle.js
exports.area=function(r){ returnr*r*Math.PI; }
使用module.exports
app.js
vararea=require('./area'); console.log(area(4));
area.js
module.exports=function(r){ returnr*r*Math.PI; }
上面两个例子输出是一样的。你也许会问,为什么不这样写呢?
app.js
vararea=require('./area'); console.log(area(4));
area.js
exports=function(r){ returnr*r*Math.PI; }
运行上面的例子会报错。这是因为,前面的例子中通过给exports添加属性,只是对exports指向的内存做了修改,而
exports=function(r){ returnr*r*Math.PI; }
其实是对exports进行了覆盖,也就是说exports指向了一块新的内存(内容为一个计算圆面积的函数),也就是说exports和module.exports不再指向同一块内存,也就是说此时exports和module.exports毫无联系,也就是说module.exports指向的那块内存并没有做任何改变,仍然为一个空对象{},也就是说area.js导出了一个空对象,所以我们在app.js中调用area(4)会报TypeError:objectisnotafunction的错误。
所以,一句话做个总结:当我们想让模块导出的是一个对象时,exports和module.exports均可使用(但exports也不能重新覆盖为一个新的对象),而当我们想导出非对象接口时,就必须也只能覆盖module.exports。
我们经常看到这样的用写法:
exports=module.exports=somethings;
上面的代码等价于
module.exports=somethings; exports=module.exports;
原因也很简单,module.exports=somethings是对module.exports进行了覆盖,此时module.exports和exports的关系断裂,module.exports指向了新的内存块,而exports还是指向原来的内存块,为了让module.exports和exports还是指向同一块内存或者说指向同一个“对象”,所以我们就exports=module.exports。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持毛票票!