详解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实用示例 缩址还原
Dec 28 NodeJs
Nodejs使用mysql模块之获得更新和删除影响的行数的方法
Mar 18 NodeJs
轻松创建nodejs服务器(7):阻塞操作的实现
Dec 18 NodeJs
NodeJs基本语法和类型
Feb 13 NodeJs
nodejs中使用多线程编程的方法实例
Mar 24 NodeJs
Nodejs 发送Post请求功能(发短信验证码例子)
Feb 09 NodeJs
深入理解nodejs中Express的中间件
May 19 NodeJs
nodeJS实现简单网页爬虫功能的实例(分享)
Jun 08 NodeJs
nodejs中sleep功能实现暂停几秒的方法
Jul 12 NodeJs
Nodejs中crypto模块的安全知识讲解
Jan 03 NodeJs
NodeJS模块与ES6模块系统语法及注意点详解
Jan 04 NodeJs
基于Koa(nodejs框架)对json文件进行增删改查的示例代码
Feb 02 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
thinkphp路由规则使用示例详解和伪静态功能实现(apache重写)
2014/02/24 PHP
PHP闭包函数详解
2016/02/13 PHP
浅析Yii2集成富文本编辑器redactor实例教程
2016/04/25 PHP
Laravel 中使用 Vue.js 实现基于 Ajax 的表单提交错误验证操作
2017/06/30 PHP
Laravel如何自定义command命令浅析
2019/03/23 PHP
ExtJs grid行 右键菜单的两种方法
2010/06/19 Javascript
JavaScript包装对象使用介绍
2013/08/29 Javascript
JQuery 文本框回车跳到下一个文本框示例代码
2013/08/30 Javascript
初步使用bootstrap快速创建页面
2016/03/03 Javascript
详解Angular的数据显示优化处理
2016/12/26 Javascript
gulp加批处理(.bat)实现ng多应用一键自动化构建
2017/02/16 Javascript
Vue 2.5 Level E 发布了: 新功能特性一览
2017/10/24 Javascript
vue使用xe-utils函数库的具体方法
2018/03/06 Javascript
jQuery实现的点击按钮改变样式功能示例
2018/07/21 jQuery
微信小程序template模板与component组件的区别和使用详解
2019/05/22 Javascript
浅谈关于vue中scss公用的解决方案
2019/12/02 Javascript
Vue Render函数创建DOM节点代码实例
2020/07/08 Javascript
Echarts在Taro微信小程序开发中的踩坑记录
2020/11/09 Javascript
从源码角度来回答keep-alive组件的缓存原理
2021/01/18 Javascript
[01:37]TI4西雅图DOTA2前线报道 VG拿下首胜教练357给出获胜秘诀
2014/07/10 DOTA
[40:27]完美世界DOTA2联赛PWL S3 PXG vs GXR 第一场 12.19
2020/12/24 DOTA
python开发之str.format()用法实例分析
2016/02/22 Python
对Python 内建函数和保留字详解
2018/10/15 Python
windows下python虚拟环境virtualenv安装和使用详解
2019/07/16 Python
python单例模式原理与创建方法实例分析
2019/10/26 Python
Python实现RGB与HSI颜色空间的互换方式
2019/11/27 Python
Python 使用双重循环打印图形菱形操作
2020/08/09 Python
YesBabyOnline美国:全球性的在线婚纱礼服工厂
2018/05/05 全球购物
安踏官方商城:anta.cn
2019/12/16 全球购物
澳大利亚领先的内衣店:Bendon Lingerie澳大利亚
2020/05/15 全球购物
办公室文员工作职责
2014/01/31 职场文书
党员违纪检讨书
2014/02/18 职场文书
成都人事代理协议书
2014/10/25 职场文书
防汛工作情况汇报
2014/10/28 职场文书
2015年大学班主任工作总结
2015/04/30 职场文书
python3实现常见的排序算法(示例代码)
2021/07/04 Python