详解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中session的简单使用及通过session实现身份验证的方法
Feb 04 NodeJs
详解NodeJs支付宝移动支付签名及验签
Jan 06 NodeJs
NodeJS配置HTTPS服务实例分享
Feb 19 NodeJs
NodeJS链接MySql数据库的操作方法
Jun 27 NodeJs
详解nodejs中express搭建权限管理系统
Sep 15 NodeJs
nodejs实现截取上传视频中一帧作为预览图片
Dec 10 NodeJs
NodeJS 将文件夹按照存放路径变成一个对应的JSON的方法
Oct 17 NodeJs
nodejs 使用http进行post或get请求的实例(携带cookie)
Jan 03 NodeJs
详解nodejs 开发企业微信第三方应用入门教程
Mar 12 NodeJs
Nodejs 识别图片类型的方法
Aug 15 NodeJs
Nodejs + sequelize 实现增删改查操作
Nov 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
php下尝试使用GraphicsMagick的缩略图功能
2011/01/01 PHP
浅析PHP中的UNICODE 编码与解码
2013/06/29 PHP
php通过ksort()函数给关联数组按照键排序的方法
2015/03/18 PHP
mailto的使用技巧分享
2012/12/21 Javascript
jquery通过visible来判断标签是否显示或隐藏
2014/05/08 Javascript
js控制网页背景音乐播放与停止的方法
2015/02/06 Javascript
JavaScript中实现map功能代码分享
2015/06/11 Javascript
JS基于cookie实现来宾统计记录访客信息的方法
2015/08/04 Javascript
详解js中构造流程图的核心技术JsPlumb
2015/12/08 Javascript
谈一谈bootstrap响应式布局
2016/05/23 Javascript
jQuery操作动态生成的内容的方法
2016/05/28 Javascript
对js eval()函数的一些见解
2016/08/15 Javascript
AngularJS 视图详解及示例代码
2016/08/17 Javascript
jQuery中的select操作详解
2016/11/29 Javascript
Vue2 SSR渲染根据不同页面修改 meta
2017/11/20 Javascript
详解webpack打包第三方类库的正确姿势
2018/10/20 Javascript
KOA+egg.js集成kafka消息队列的示例
2018/11/09 Javascript
[05:15]2018年度CS GO社区贡献奖-完美盛典
2018/12/16 DOTA
Python自动化测试Eclipse+Pydev 搭建开发环境
2016/08/15 Python
python实现动态数组的示例代码
2019/07/15 Python
python实现的config文件读写功能示例
2019/09/24 Python
python之MSE、MAE、RMSE的使用
2020/02/24 Python
tensorflow模型的save与restore,及checkpoint中读取变量方式
2020/05/26 Python
Django contrib auth authenticate函数源码解析
2020/11/12 Python
Matplotlib中rcParams使用方法
2021/01/05 Python
人力资源管理专业应届生求职信
2014/04/24 职场文书
五四青年节演讲稿
2014/05/26 职场文书
2015年民主生活会发言材料
2014/12/15 职场文书
实习介绍信模板
2015/01/30 职场文书
2015年领班工作总结
2015/04/29 职场文书
领导干部失职检讨书
2015/05/05 职场文书
机关工会工作总结2015
2015/05/26 职场文书
丧事主持词
2015/07/02 职场文书
幼儿园心得体会范文
2016/01/21 职场文书
Html5调用企业微信的实现
2021/04/16 HTML / CSS
Python实现8种常用抽样方法
2021/06/27 Python