详解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实现获取当前url地址及url各种参数值
Jun 25 NodeJs
NodeJS远程代码执行
Aug 28 NodeJs
nodejs的HTML分析利器node-jquery用法浅析
Nov 08 NodeJs
nodejs搭建本地服务器并访问文件的方法
Mar 03 NodeJs
详解nodeJS中读写文件方法的区别
Mar 06 NodeJs
win系统下nodejs环境安装配置
May 04 NodeJs
nodejs multer实现文件上传与下载
May 10 NodeJs
详解nodejs中express搭建权限管理系统
Sep 15 NodeJs
nodejs aes 加解密实例
Oct 10 NodeJs
NodeJS模块与ES6模块系统语法及注意点详解
Jan 04 NodeJs
详解nodejs http请求相关总结
Mar 31 NodeJs
nodejs实现用户登录路由功能
May 22 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默认安装产生系统漏洞
2006/10/09 PHP
php 结果集的分页实现代码
2009/03/10 PHP
PHP反射机制用法实例
2014/08/28 PHP
PHP使用mysql_fetch_row查询获得数据行列表的方法
2015/03/18 PHP
Thinkphp框架使用list_to_tree 实现无限级分类列出所有节点示例
2020/04/04 PHP
一句话JavaScript表单验证代码
2009/08/02 Javascript
js 获取浏览器高度和宽度值(多浏览器)
2009/09/02 Javascript
javascript学习笔记(八)正则表达式
2014/10/08 Javascript
jQuery实现的产品自动360度旋转展示特效源码分享
2015/08/21 Javascript
详解JavaScript中的4种类型识别方法
2015/09/14 Javascript
JavaScript数组方法总结分析
2016/05/06 Javascript
轻松搞定js表单验证
2016/10/13 Javascript
原生js实现查询天气小应用
2016/12/09 Javascript
vue.js实现标签页切换效果
2018/06/07 Javascript
Vue.js 中取得后台原生HTML字符串 原样显示问题的解决方法
2018/06/10 Javascript
vue中的计算属性实例详解
2018/09/19 Javascript
一步步教你利用Docker设置Node.js
2018/11/20 Javascript
Vue2.x通用编辑组件的封装及应用详解
2019/05/28 Javascript
使用layer.msg 时间设置不起作用的解决方法
2019/09/12 Javascript
js实现无缝轮播图
2020/03/09 Javascript
Vue.js获取手机系统型号、版本、浏览器类型的示例代码
2020/05/10 Javascript
[02:06]DOTA2肉山黑名单魔法终结者 敌法师中文配音鉴赏
2013/06/17 DOTA
和孩子一起学习python之变量命名规则
2018/05/27 Python
关于python导入模块import与常见的模块详解
2019/08/28 Python
matplotlib 使用 plt.savefig() 输出图片去除旁边的空白区域
2021/01/05 Python
俄罗斯商务邀请函
2014/01/26 职场文书
个人简历自我评价范文
2014/02/04 职场文书
安全生产承诺书
2014/03/26 职场文书
高一课前三分钟演讲稿
2014/09/13 职场文书
铅球加油稿100字
2014/09/26 职场文书
民主评议党员总结
2014/10/20 职场文书
见习报告格式要求
2014/11/04 职场文书
硕士论文致谢范文
2015/05/14 职场文书
咖啡厅里的创业计划书
2019/08/21 职场文书
台式电脑蓝牙适配器怎么安装?台式电脑蓝牙适配器安装教程
2022/04/08 数码科技
JS前端使用canvas实现扩展物体类和事件派发
2022/08/05 Javascript