详解nodejs中exports和module.exports的区别


Posted in NodeJs onFebruary 17, 2017

require 用来加载代码,而 exports 和 module.exports 则用来导出代码。但很多新手可能会迷惑于 exports 和 module.exports 的区别,为了更好的理解 exports 和 module.exports 的关系,我们先来巩固下 js 的基础。示例:

app.js

var a = {name: 'nswbmw 1'};
var b = a;
console.log(a);
console.log(b);
b.name = 'nswbmw 2';
console.log(a);
console.log(b);
var b = {name: 'nswbmw 3'};
console.log(a);
console.log(b);

运行 app.js 结果为:

{ name: 'nswbmw 1' }
{ name: 'nswbmw 1' }
{ name: 'nswbmw 2' }
{ name: 'nswbmw 2' }
{ name: 'nswbmw 2' }
{ name: 'nswbmw 3' }

解释一下: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

所以:我们通过

var name = 'nswbmw';
exports.name = name;
exports.sayName = function() {
 console.log(name);
}

给 exports 赋值其实是给 module.exports 这个空对象添加了两个属性而已,上面的代码相当于:

var name = 'nswbmw';
module.exports.name = name;
module.exports.sayName = function() {
 console.log(name);
}

我们通常这样使用 exports 和 module.exports

一个简单的例子,计算圆的面积:

使用 exports

app.js

var circle = require('./circle');
console.log(circle.area(4));

circle.js

exports.area = function(r) {
 return r * r * Math.PI;
}

使用 module.exports

app.js

var area = require('./area');
console.log(area(4));

area.js

module.exports = function(r) {
 return r * r * Math.PI;
}

上面两个例子输出是一样的。你也许会问,为什么不这样写呢?

app.js

var area = require('./area');
console.log(area(4));

area.js

exports = function(r) {
 return r * r * Math.PI;
}

运行上面的例子会报错。这是因为,前面的例子中通过给 exports 添加属性,只是对 exports 指向的内存做了修改,而

exports = function(r) {
 return r * r * Math.PI;
}

其实是对 exports 进行了覆盖,也就是说 exports 指向了一块新的内存(内容为一个计算圆面积的函数),也就是说 exports 和 module.exports 不再指向同一块内存,也就是说此时 exports 和 module.exports 毫无联系,也就是说 module.exports 指向的那块内存并没有做任何改变,仍然为一个空对象 {} ,也就是说 area.js 导出了一个空对象,所以我们在 app.js 中调用 area(4) 会报 TypeError: object is not a function 的错误。

所以,一句话做个总结:当我们想让模块导出的是一个对象时,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。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

NodeJs 相关文章推荐
nodejs入门详解(多篇文章结合)
Mar 07 NodeJs
利用NodeJS和PhantomJS抓取网站页面信息以及网站截图
Nov 18 NodeJs
nodejs npm package.json中文文档
Sep 04 NodeJs
Nodejs全栈框架StrongLoop推荐
Nov 09 NodeJs
快速掌握Node.js之Window下配置NodeJs环境
Mar 21 NodeJs
浅析Nodejs npm常用命令
Jun 14 NodeJs
NodeJS处理Express中异步错误
Mar 26 NodeJs
详解nodejs爬虫程序解决gbk等中文编码问题
Apr 06 NodeJs
详解nodejs微信公众号开发——6.自定义菜单
Apr 13 NodeJs
NodeJS 实现手机短信验证模块阿里大于功能
Jun 19 NodeJs
Nodejs把接收图片base64格式保存为文件存储到服务器上
Sep 26 NodeJs
NodeJS 将文件夹按照存放路径变成一个对应的JSON的方法
Oct 17 NodeJs
Nodejs+Socket.io实现通讯实例代码
Feb 13 #NodeJs
Nodejs高扩展性的模板引擎 functmpl简介
Feb 13 #NodeJs
Nodejs 发送Post请求功能(发短信验证码例子)
Feb 09 #NodeJs
Nodejs实现短信验证码功能
Feb 09 #NodeJs
Express与NodeJs创建服务器的两种方法
Feb 06 #NodeJs
使用nodejs下载风景壁纸
Feb 05 #NodeJs
nodeJs链接Mysql做增删改查的简单操作
Feb 04 #NodeJs
You might like
PHP 日期加减的类,很不错
2009/10/10 PHP
360搜索引擎自动收录php改写方案
2018/04/28 PHP
js表数据排序 sort table data
2009/02/18 Javascript
JQuery学习笔录 简单的JQuery
2012/04/09 Javascript
拉动滚动条加载数据的jquery代码
2012/05/03 Javascript
火狐textarea输入法的bug的触发及解决
2013/07/24 Javascript
JS.elementGetStyle(element, style)应用示例
2013/09/24 Javascript
JS实现控制表格单元格垂直对齐的方法
2015/03/30 Javascript
基于Jquery实现仿百度百科右侧导航代码附源码下载
2015/11/27 Javascript
使用angularjs创建简单表格
2016/01/21 Javascript
浅析Bootstrap验证控件的使用
2016/06/23 Javascript
深入理解vue.js双向绑定的实现原理
2016/12/05 Javascript
layui弹出层效果实现代码
2017/05/19 Javascript
javascript基础进阶_深入剖析执行环境及作用域链
2017/09/05 Javascript
D3.js实现拓扑图的示例代码
2018/06/30 Javascript
vue实现的仿淘宝购物车功能详解
2019/01/27 Javascript
使用layui的layer组件做弹出层的例子
2019/09/27 Javascript
关于layui的下拉搜索框异步加载数据的解决方法
2019/09/28 Javascript
JS实现简单日历特效
2020/01/03 Javascript
详解React路由传参方法汇总记录
2020/11/29 Javascript
[01:02:02]DOTA2上海特级锦标赛A组败者赛 EHOME VS CDEC第二局
2016/02/25 DOTA
Python实现扫描局域网活动ip(扫描在线电脑)
2015/04/28 Python
解读Python中degrees()方法的使用
2015/05/18 Python
老生常谈Python startswith()函数与endswith函数
2017/09/08 Python
Python复制Word内容并使用格式设字体与大小实例代码
2018/01/22 Python
详解python如何在django中为用户模型添加自定义权限
2018/10/15 Python
python判断一个对象是否可迭代的例子
2019/07/22 Python
python爬虫实现POST request payload形式的请求
2020/04/30 Python
HTML5中语义化 b 和 i 标签
2008/10/17 HTML / CSS
毕业生自荐信
2013/12/14 职场文书
先进事迹报告会主持词
2014/04/02 职场文书
园林技术专业求职信
2014/07/28 职场文书
单位工作证明范文
2014/09/14 职场文书
2014年教育教学工作总结
2014/11/13 职场文书
房产公证书格式
2015/01/26 职场文书
社区干部培训心得体会
2016/01/06 职场文书