详解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+express+html5 实现拖拽上传
Aug 08 NodeJs
nodejs中转换URL字符串与查询字符串详解
Nov 26 NodeJs
使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
Aug 21 NodeJs
Nodejs高扩展性的模板引擎 functmpl简介
Feb 13 NodeJs
Nodejs基于LRU算法实现的缓存处理操作示例
Mar 17 NodeJs
Nodejs之TCP服务端与客户端聊天程序详解
Jul 07 NodeJs
Windows下使用Nodejs运行js的方法
Sep 02 NodeJs
NodeJS读取分析Nginx错误日志的方法
May 14 NodeJs
nodejs对项目下所有空文件夹创建gitkeep的方法
Aug 02 NodeJs
NodeJs crypto加密制作token的实现代码
Nov 15 NodeJs
Nodejs 微信小程序消息推送的实现
Jan 20 NodeJs
分享五个Node.js开发的优秀实践 
Apr 07 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
phpmyadmin安装时提示:Warning: require_once(./libraries/common.inc.php)错误解决办法
2011/08/18 PHP
php中有关合并某一字段键值相同的数组合并的改进
2015/03/10 PHP
PHP构造二叉树算法示例
2017/06/21 PHP
PHP8.0新功能之Match表达式的使用
2020/07/19 PHP
XAMPP升级PHP版本实现步骤解析
2020/09/04 PHP
jQuery入门第一课 jQuery选择符
2010/03/14 Javascript
js判断客户端是iOS还是Android等移动终端的方法
2013/12/11 Javascript
HTML5 Shiv完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法
2015/11/25 Javascript
JavaScript的Vue.js库入门学习教程
2016/05/23 Javascript
详解jQuery中的deferred对象的使用(一)
2016/05/27 Javascript
JS解决移动web开发手机输入框弹出的问题
2017/03/31 Javascript
详解VUE-地区选择器(V-Distpicker)组件使用心得
2018/05/07 Javascript
Vue props 单向数据流的实现
2018/11/06 Javascript
微信小程序自定义底部导航带跳转功能
2018/11/27 Javascript
使用vuex解决刷新页面state数据消失的问题记录
2019/05/08 Javascript
layui-table表复选框勾选的所有行数据获取的例子
2019/09/13 Javascript
Vuex中实现数据状态查询与更改
2019/11/08 Javascript
JS实现滑动导航效果
2020/01/14 Javascript
javascript中可能用得到的全部的排序算法
2020/03/05 Javascript
Python统计日志中每个IP出现次数的方法
2015/07/06 Python
详解Python nose单元测试框架的安装与使用
2017/12/20 Python
python中的for循环
2018/09/28 Python
python ChainMap的使用和说明详解
2019/06/11 Python
python实现画图工具
2020/08/27 Python
css背景图片的背景裁切、背景透明度、背景变换等效果运用
2012/12/24 HTML / CSS
工程材料采购方案
2014/05/18 职场文书
医学求职自荐信
2014/06/21 职场文书
节电标语大全
2014/06/23 职场文书
2015年挂职锻炼工作总结
2014/12/12 职场文书
上市公司董事长岗位职责
2015/04/16 职场文书
2015年食堂工作总结报告
2015/04/23 职场文书
2015年计划生育责任书
2015/05/08 职场文书
就业证明函
2015/06/17 职场文书
MySQL 8.0 Online DDL快速加列的相关总结
2021/06/02 MySQL
SpringDataJPA在Entity中常用的注解介绍
2021/12/06 Java/Android
MySQL创建管理子分区
2022/04/13 MySQL